import sys
import pandas as pd
import streamlit as st
import plotly.express as px
from urllib.parse import quote_plus
from sqlalchemy import create_engine

# --- Configuração do Terminal (Windows) ---
if sys.platform == "win32":
    sys.stdout.reconfigure(encoding='utf-8', errors='replace')
    sys.stderr.reconfigure(encoding='utf-8', errors='replace')

# --- Configuração da Página Streamlit ---
st.set_page_config(page_title="Dashboard de Vendas", layout="wide")

# --- Design Tokens ---
BG_MAIN  = "#0a0a0f"
BG_CARD  = "#1a1a24"
C_GREEN  = "#00d4aa"
C_BLUE   = "#4d9fff"
C_ORANGE = "#ff8c42"
C_PURPLE = "#b06cff"
C_RED    = "#ff4d6d"
C_TEXT   = "#e8e8f0"
C_MUTED  = "#8888a0"
C_BORDER = "rgba(255,255,255,0.08)"

PALETTE = [C_BLUE, C_GREEN, C_ORANGE, C_PURPLE, "#ffd166", "#06d6a0", "#ef476f", "#118ab2", "#a855f7", "#ec4899"]

# --- Injeção de CSS Dark no Streamlit ---
st.markdown(f"""
    <style>
        .stApp {{
            background-color: {BG_MAIN};
            color: {C_TEXT};
        }}
        [data-testid="stSidebar"] {{
            background-color: {BG_CARD};
            border-right: 1px solid {C_BORDER};
        }}
        .stExpander, div[data-testid="stMetricValue"] {{
            background-color: {BG_CARD};
            border: 1px solid {C_BORDER};
            border-radius: 8px;
        }}
        h1, h2, h3, h4, h5, h6, label, .stMarkdown {{
            color: {C_TEXT} !important;
        }}
    </style>
""", unsafe_allow_html=True)

# --- Configurações do Banco de Dados ---
DB_HOST = '127.0.0.1'
DB_PORT = 5432
DB_USER = 'postgres'
DB_PASSWORD = 'ps@web'
DB_NAME = 'bdps01'

@st.cache_resource
def get_engine():
    """Cria e armazena em cache o engine de conexão com o PostgreSQL."""
    password_encoded = quote_plus(DB_PASSWORD)
    url = f"postgresql+psycopg2://{DB_USER}:{password_encoded}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
    
    return create_engine(
        url,
        connect_args={"client_encoding": "win1252"}
    )

@st.cache_data(ttl=600)
def carregar_dados_vendas():
    """Busca os dados detalhados no banco trazendo município e nome do cliente."""
    engine = get_engine()
    
    query = """
        SELECT 
            v.filial, 
            p.descricao_posicionamento, 
            v.data_nota, 
            c.municipio,
            c.nome_cliente,
            v.valor_produto
        FROM vw_vendas_produtos_langchain v
        INNER JOIN vw_clientes c ON v.codigo_cliente = c.codigo_cliente
        INNER JOIN vw_posic p ON v.posicionamento_produto = p.posicionamento
        WHERE EXTRACT(YEAR FROM v.data_nota) = 2026
        ORDER BY v.data_nota;
    """
    
    try:
        df = pd.read_sql(query, con=engine)
        
        if not df.empty and 'data_nota' in df.columns:
            df['data_nota'] = pd.to_datetime(df['data_nota'])
            df['Mes'] = df['data_nota'].dt.strftime('%m/%Y')
            df['Data_Formatada'] = df['data_nota'].dt.strftime('%Y-%m-%d')
            
        return df
    except Exception as e:
        st.error(f"Erro ao conectar ou consultar o banco de dados: {e}")
        return pd.DataFrame()

# --- Carregamento dos Dados ---
df_vendas = carregar_dados_vendas()

if df_vendas.empty:
    st.warning("Nenhum dado encontrado para o ano de 2026 ou falha na conexão.")
    st.stop()

# --- Barra Lateral (Filtros) ---
st.sidebar.header("Filtros")

# Filtro de Mês com opção do Ano Inteiro
OPCAO_ANO = "Ano Todo (2026)"
meses_disponiveis = [OPCAO_ANO] + sorted(df_vendas["Mes"].unique().tolist())
mes_selecionado = st.sidebar.selectbox("Selecione o Periodo", meses_disponiveis)

# Aplicação do Filtro
if mes_selecionado == OPCAO_ANO:
    df_filtrado = df_vendas.copy()
else:
    df_filtrado = df_vendas[df_vendas["Mes"] == mes_selecionado].copy()

# --- Funções de Agrupamento Top N + OUTROS ---
def agrupar_top_n(df, coluna_agrupamento, coluna_valor, n=20):
    top_items = (
        df.groupby(coluna_agrupamento)[coluna_valor]
        .sum()
        .nlargest(n)
        .index
    )
    return df[coluna_agrupamento].apply(lambda x: x if x in top_items else "OUTROS")

# Processamento dos agrupamentos
top_produtos = (
    df_filtrado.groupby("descricao_posicionamento")["valor_produto"]
    .sum()
    .nlargest(10)
    .index
)
df_filtrado["produto_agrupado"] = df_filtrado["descricao_posicionamento"].apply(
    lambda x: x if x in top_produtos else "OUTROS"
)

df_filtrado["municipio_agrupado"] = agrupar_top_n(df_filtrado, "municipio", "valor_produto", n=20)
df_filtrado["cliente_agrupado"] = agrupar_top_n(df_filtrado, "nome_cliente", "valor_produto", n=20)

# --- Painel Principal ---
st.title("📊 Dashboard de Vendas - 2026")
st.markdown(f"Exibindo dados do mês: **{mes_selecionado}**")

# Exibição da tabela filtrada
#with st.expander("Visualizar Tabela de Dados"):
#    st.dataframe(df_filtrado, width="stretch")

# --- Função de Estilização Dark para Plotly ---
def aplicar_estilo_dark(fig, esconder_legenda=False, altura=400):
    fig.update_layout(
        height=altura,  # Define a altura em pixels
        paper_bgcolor=BG_CARD,
        plot_bgcolor=BG_CARD,
        font=dict(color=C_TEXT, family="Roboto, sans-serif"),
        title_font_color=C_TEXT,
        xaxis=dict(gridcolor=C_BORDER, color=C_MUTED, zerolinecolor=C_BORDER),
        yaxis=dict(gridcolor=C_BORDER, color=C_MUTED, zerolinecolor=C_BORDER),
        legend=dict(font=dict(color=C_TEXT)),
        showlegend=not esconder_legenda
    )
    return fig

# --- PRIMEIRA LINHA DE GRÁFICOS ---
col1, col2 = st.columns(2)

# Gráfico 1: Top 10 Categorias de Produtos + Outros (Multicolorido)
with col1:
    df_top = (
        df_filtrado.groupby("produto_agrupado", as_index=False)["valor_produto"]
        .sum()
        .sort_values(by="valor_produto", ascending=False)
    )
    
    fig_prod = px.bar(
        df_top, 
        x="valor_produto", 
        y="produto_agrupado", 
        color="produto_agrupado",
        orientation="h",
        title="Top 10 Posicionamento de Produtos (Faturamento)",
        labels={"valor_produto": "Total (R$)", "produto_agrupado": "Posicionamento"},
        color_discrete_sequence=PALETTE
    )
    fig_prod.update_layout(yaxis={'categoryorder': 'total ascending'})
    fig_prod = aplicar_estilo_dark(fig_prod, esconder_legenda=True)
    st.plotly_chart(fig_prod, width="stretch")

# Gráfico 2: Vendas por Filial (Barras Verticais)
with col2:
    df_filial = (
        df_filtrado.groupby("filial", as_index=False)["valor_produto"]
        .sum()
        .sort_values(by="valor_produto", ascending=False)
    )
    
    fig_filial = px.bar(
        df_filial, 
        x="filial", 
        y="valor_produto",
        color="filial",
        title="Faturamento por Filial",
        labels={"valor_produto": "Total (R$)", "filial": "Filial"},
        color_discrete_sequence=PALETTE
    )
    fig_filial = aplicar_estilo_dark(fig_filial, esconder_legenda=True)
    st.plotly_chart(fig_filial, width="stretch")

# --- SEGUNDA LINHA DE GRÁFICOS ---
col3, col4 = st.columns(2)

# Gráfico 3: Top 20 Municípios + Outros (Multicolorido)
with col3:
    df_muni = (
        df_filtrado.groupby("municipio_agrupado", as_index=False)["valor_produto"]
        .sum()
        .sort_values(by="valor_produto", ascending=False)
    )


# Gráfico 3: Top 20 Municípios + Outros (Multicolorido)
# --- SEGUNDA LINHA DE GRÁFICOS ---
col3, col4 = st.columns(2)

# Gráfico 3: Top 20 Municípios + Outros (Multicolorido)
with col3:
    df_muni = (
        df_filtrado.groupby("municipio_agrupado", as_index=False)["valor_produto"]
        .sum()
        .sort_values(by="valor_produto", ascending=False)
    )
    
    # 1. Cria a figura
    fig_muni = px.bar(
        df_muni, 
        x="valor_produto", 
        y="municipio_agrupado", 
        color="municipio_agrupado",
        orientation="h",
        title="Top 20 Municípios (Faturamento)",
        labels={"valor_produto": "Total (R$)", "municipio_agrupado": "Município"},
        color_discrete_sequence=PALETTE
    )
    fig_muni.update_layout(yaxis={'categoryorder': 'total ascending'})
    
    # 2. Aplica o estilo dark com altura de 700px
    fig_muni = aplicar_estilo_dark(fig_muni, esconder_legenda=True, altura=700)
    
    # 3. Renderiza no Streamlit
    st.plotly_chart(fig_muni, width="stretch")

# Gráfico 4: Top 20 Clientes + Outros (Multicolorido)
with col4:
    df_cli = (
        df_filtrado.groupby("cliente_agrupado", as_index=False)["valor_produto"]
        .sum()
        .sort_values(by="valor_produto", ascending=False)
    )
    
    # 1. Cria a figura
    fig_cli = px.bar(
        df_cli,
        x="valor_produto", 
        y="cliente_agrupado", 
        color="cliente_agrupado",
        orientation="h",
        title="Top 20 Clientes (Faturamento)",
        labels={"valor_produto": "Total (R$)", "cliente_agrupado": "Cliente"},
        color_discrete_sequence=PALETTE
    )
    fig_cli.update_layout(yaxis={'categoryorder': 'total ascending'})
    
    # 2. Aplica o estilo dark com altura de 700px
    fig_cli = aplicar_estilo_dark(fig_cli, esconder_legenda=True, altura=700)
    
    # 3. Renderiza no Streamlit
    st.plotly_chart(fig_cli, width="stretch")