# /frontend/pages/conversations.py
import dash
from dash import html, dcc, callback, Input, Output, State, no_update
import dash_bootstrap_components as dbc
import requests
from dateutil.parser import parse as parse_date
from dash.exceptions import PreventUpdate

from config import CHATBOT_API_URL, CHATBOT_API_TOKEN, DOCS_USERNAME, DOCS_PASSWORD

dash.register_page(__name__, path='/conversations', name='Histórico de Conversas', order=2)

HEADERS = {"Authorization": f"Bearer {CHATBOT_API_TOKEN}"}
USE_AUTHENTICATION = True

def get_all_sessions(search_term=None):
    params = {"search": search_term} if search_term else {}
    try:
        res = requests.get(f"{CHATBOT_API_URL}/sessions", headers=HEADERS, params=params)
        res.raise_for_status()
        return res.json()
    except requests.exceptions.RequestException as e:
        return [{"error": f"Erro de conexão ao buscar sessões: {e}"}]
    except Exception as e:
        return [{"error": f"Erro inesperado ao buscar sessões: {e}"}]

def get_session_history(session_id):
    try:
        res = requests.get(f"{CHATBOT_API_URL}/sessions/{session_id}/history", headers=HEADERS)
        res.raise_for_status()
        return res.json()
    except requests.exceptions.RequestException as e:
        return [{"error": f"Erro de conexão ao buscar histórico: {e}"}]
    except Exception as e:
        return [{"error": f"Erro inesperado ao buscar histórico: {e}"}]

def layout():
    """Página de histórico sem modal local; usa o modal global do app.py."""
    return html.Div([
        # store desta página (o search-term-store virou GLOBAL no app.py)
        dcc.Store(id='selected-session-store'),

        # área de conteúdo
        html.Div(
            id="content-col-conv",
            className="content-col position-relative",
            children=[
                dcc.Loading(id="loading-history", children=html.Div(id="history-display"))
            ]
        )
    ])

# 0) Sidebar dinâmica: só renderiza UI após autenticação
@callback(
    Output("conv-sidebar-proxy", "children"),
    Input("_pages_location", "pathname"),
    Input("auth-store-conv", "data"),
    prevent_initial_call=False
)
def render_conv_sidebar(pathname, auth_data):
    if pathname != "/conversations":
        raise PreventUpdate

    authed = bool(auth_data and auth_data.get("authenticated"))
    if not authed:
        return html.Div([
            html.P("🔒 Área restrita. Autentique-se para visualizar as sessões.", className="text-muted")
        ])

    return html.Div([
        html.H5("🔍 Buscar Sessões"),
        dbc.InputGroup([
            dbc.Input(id="search-input", placeholder="Filtro de texto...", n_submit=0),
            dbc.Button("Buscar", id="search-btn", n_clicks=0),
        ]),
        dbc.Button("Limpar Busca", id="clear-search-btn", color="secondary", className="mt-2 w-100"),
        html.Hr(),
        html.H5("Sessões disponíveis"),
        dcc.Loading(id="loading-sessions", children=html.Div(id="session-list", style={"max-height": "60vh", "overflowY": "auto"}))
    ])

# 1) Autenticação no histórico (modal e store são GLOBAIS em app.py)
# NOTA: O layout do modal em app.py precisa ser atualizado para incluir um campo de usuário com id='username-input-conv'
@callback(
    Output('auth-modal-conv', 'is_open'),
    Output('auth-store-conv', 'data'),
    Output('username-input-conv', 'invalid'),
    Output('password-input-conv', 'invalid'),
    Input('_pages_location', 'pathname'),
    Input('password-submit-conv', 'n_clicks'),
    State('auth-store-conv', 'data'),
    State('username-input-conv', 'value'),
    State('password-input-conv', 'value'),
    prevent_initial_call=False
)
def handle_auth(pathname, submit_clicks, auth_data, username_value, password_value):
    if pathname != "/conversations":
        raise PreventUpdate

    authed = bool(auth_data and auth_data.get("authenticated"))

    # Na carga da página, abre o modal se não estiver autenticado. Não marca campos como inválidos.
    if not dash.ctx.triggered_id or dash.ctx.triggered_id == "_pages_location":
        if authed:
            return False, auth_data, False, False
        return True, auth_data, False, False

    # Ao clicar em submeter
    if dash.ctx.triggered_id == "password-submit-conv":
        # Se as credenciais estiverem corretas, fecha o modal e autentica
        if username_value == DOCS_USERNAME and password_value == DOCS_PASSWORD:
            return False, {"authenticated": True}, False, False
        
        # Se estiverem incorretas, mantém o modal aberto e marca ambos os campos como inválidos
        return True, no_update, True, True

    raise PreventUpdate

# 2) Buscar / limpar busca → escreve no store GLOBAL search-term-store
@callback(
    Output('search-term-store', 'data'),
    Output('search-input', 'value', allow_duplicate=True),
    Input('search-btn', 'n_clicks'),
    Input('clear-search-btn', 'n_clicks'),
    Input('search-input', 'n_submit'),
    State('search-input', 'value'),
    prevent_initial_call=True
)
def update_search_term(search_click, clear_click, enter_press, search_value):
    trigger = dash.ctx.triggered_id
    if trigger in ['search-btn', 'search-input']:
        return (search_value or ""), no_update
    if trigger == 'clear-search-btn':
        return "", ""
    return no_update, no_update

# 3) Carregar lista de sessões (só roda autenticado)
@callback(
    Output('session-list', 'children'),
    Input('search-term-store', 'data'),
    Input('auth-store-conv', 'data')
)
def load_session_list(search_term, auth_data):
    if not (auth_data and auth_data.get('authenticated')):
        return html.P("🔒 Autentique-se para ver as sessões.")

    sessions = get_all_sessions(search_term)
    if not sessions:
        return html.P("Nenhuma sessão encontrada.")
    if "error" in sessions[0]:
        return dbc.Alert(sessions[0].get("error"), color="danger")

    items = []
    for s in sessions:
        sid = s.get("session_id", "sem id")
        source = s.get("source", "sem origem")
        ts_str = parse_date(s.get("timestamp")).strftime("%d/%m/%Y %H:%M") if s.get("timestamp") else "sem data"

        content = html.Div([
            html.Div([html.Strong("id"), html.Span(": "), html.Code(sid)], className="mb-1"),
            html.Div([html.Strong("source"), html.Span(": "), html.Span(source)], className="mb-1"),
            html.Div([html.Strong("date"), html.Span(": "), html.Span(ts_str)], className="mb-0"),
        ], style={"whiteSpace": "normal"})

        items.append(
            dbc.Button(
                content,
                id={"type": "session-select-btn", "index": sid},
                color="light",
                className="w-100 mb-2 text-start",
            )
        )
    return items

# 4) Selecionar sessão
@callback(
    Output('selected-session-store', 'data'),
    Input({"type": "session-select-btn", "index": dash.ALL}, "n_clicks"),
    prevent_initial_call=True
)
def select_session(clicks):
    if not any(clicks):
        return no_update
    triggered_id = dash.ctx.triggered_id
    return triggered_id['index']

# 5) Mostrar histórico
@callback(
    Output('history-display', 'children'),
    Input('selected-session-store', 'data')
)
def display_history(session_id):
    if not session_id:
        return html.H4("Selecione uma sessão na barra lateral para ver o histórico.", className="text-muted text-center mt-5")

    history = get_session_history(session_id)
    if not history:
        return dbc.Alert("Não foi possível carregar o histórico ou ele está vazio.", color="warning")
    if "error" in history[0]:
        return dbc.Alert(history[0].get("error"), color="danger")

    header = html.Div([
        html.H3([
            "💬 Histórico da Conversa ",
            html.Span(session_id, style={'color':'#003da5', 'font-weight':'bold'}),
        ]),
        dbc.Button("🔗 Abrir no Chat", id="open-in-chat-btn", n_clicks=0, color="primary", className="mt-2")
    ])

    entries = []
    for entry in history:
        ts = entry.get("timestamp")
        ts_str = parse_date(ts).strftime('%d/%m/%Y %H:%M:%S') if isinstance(ts, str) else "sem data"
        entries.append(html.Div([
            html.P(f"🕓 {ts_str}", style={'font-weight': 'bold'}),
            html.P([html.Strong("Usuário: "), entry.get('user_input', 'N/A')]),
            html.Div([html.Strong("Agente: "), dcc.Markdown(entry.get('agent_response', 'N/A'), dangerously_allow_html=True)])
        ], className="history-entry"))

    return [header] + entries

# 6) Navegar para o chat (altera URL e página)
@callback(
    Output("_pages_location", "pathname"),
    Output("_pages_location", "search"),
    Input("open-in-chat-btn", "n_clicks"),
    State("selected-session-store", "data"),
    prevent_initial_call=True
)
def go_to_chat(n_clicks, session_id):
    if not n_clicks or not session_id:
        raise PreventUpdate
    return "/chatbot", f"?session_id={session_id}"
