"""
Dashboard, call history, and related endpoints expected by the React app (/api/...).
"""

from __future__ import annotations

import json
import time
from typing import Any

from django.db import connections
from django.http import HttpResponseForbidden, StreamingHttpResponse
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from config.reporting_utils import (
    _legacy_profile_for_user,
    _admin_role,
    cluster_table_exists,
    fetch_active_calls_count,
    fetch_call_history_page,
    fetch_dashboard_charts,
    fetch_dashboard_stats,
)


def _resolve_legacy(request) -> dict[str, Any] | None:
    return _legacy_profile_for_user(request.user)


def _parse_int(q: dict, key: str, default: int, *, min_v: int = 0, max_v: int = 10_000) -> int:
    try:
        v = int(q.get(key, default))
    except (TypeError, ValueError):
        v = default
    return max(min_v, min(v, max_v))


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def dashboard_stats(request):
    legacy = _resolve_legacy(request)
    if not legacy or legacy.get("business_id") is None:
        return Response(
            {"detail": "No business profile found for this user."},
            status=400,
        )
    return Response(fetch_dashboard_stats(legacy))


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def dashboard_charts(request):
    legacy = _resolve_legacy(request)
    if not legacy or legacy.get("business_id") is None:
        return Response(
            {"detail": "No business profile found for this user."},
            status=400,
        )
    date_from = (request.query_params.get("date_from") or "").strip() or None
    date_to = (request.query_params.get("date_to") or "").strip() or None
    return Response(fetch_dashboard_charts(legacy, date_from, date_to))


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def active_calls(request):
    legacy = _resolve_legacy(request)
    if not legacy or legacy.get("business_id") is None:
        return Response({"success": False, "count": 0, "message": "No business profile"}, status=400)
    recent = _parse_int(request.query_params, "recent_minutes", 5, min_v=1, max_v=1440)
    count = fetch_active_calls_count(legacy, recent)
    return Response({"success": True, "count": count})


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def attempted_call_history(request):
    legacy = _resolve_legacy(request)
    if not legacy or legacy.get("business_id") is None:
        return Response(
            {"success": False, "data": [], "total": 0, "message": "No business profile"},
            status=400,
        )
    bid = int(legacy["business_id"])
    limit = _parse_int(request.query_params, "limit", 100, min_v=1, max_v=500)
    offset = _parse_int(request.query_params, "offset", 0, min_v=0, max_v=1_000_000)

    if not cluster_table_exists("business_id_callhistory"):
        return Response({"success": True, "data": [], "total": 0, "limit": limit, "offset": offset})

    agent_filter_sql = ""
    agent_params: list[Any] = []
    if not _admin_role(legacy.get("role")) and legacy.get("agent_id") is not None:
        agent_filter_sql = " AND user_id = %s"
        agent_params = [int(legacy["agent_id"])]

    start_date = (request.query_params.get("start_date") or "").strip() or None
    end_date = (request.query_params.get("end_date") or "").strip() or None
    cust = (request.query_params.get("customer_number") or "").strip() or None

    where_extra = ""
    params_prefix: list[Any] = [bid]
    if start_date:
        where_extra += " AND call_started_at >= %s"
        params_prefix.append(start_date)
    if end_date:
        where_extra += " AND call_started_at < DATE_ADD(%s, INTERVAL 1 DAY)"
        params_prefix.append(end_date)
    if cust:
        where_extra += " AND CAST(metadata AS CHAR) LIKE %s"
        params_prefix.append(f"%{cust}%")

    count_sql = f"""
        SELECT COUNT(*) FROM business_id_callhistory
        WHERE business_id = %s {where_extra} {agent_filter_sql}
    """
    list_sql = f"""
        SELECT user_id, call_started_at, call_ended_at, duration_seconds, status, metadata, created_at
        FROM business_id_callhistory
        WHERE business_id = %s {where_extra} {agent_filter_sql}
        ORDER BY created_at DESC
        LIMIT %s OFFSET %s
    """

    try:
        with connections["cluster"].cursor() as cur:
            cur.execute(count_sql, [*params_prefix, *agent_params])
            total_row = cur.fetchone()
            total = int(total_row[0] or 0) if total_row else 0
            cur.execute(list_sql, [*params_prefix, *agent_params, limit, offset])
            cols = [c[0] for c in cur.description]
            rows = [dict(zip(cols, r)) for r in cur.fetchall()]
    except Exception:
        return Response({"success": True, "data": [], "total": 0, "limit": limit, "offset": offset})

    out: list[dict[str, Any]] = []
    for r in rows:
        md = r.get("metadata") or {}
        if isinstance(md, str):
            try:
                md = json.loads(md)
            except Exception:
                md = {}
        if not isinstance(md, dict):
            md = {}
        started = r.get("call_started_at")
        out.append(
            {
                "agentname": md.get("agentname") or md.get("agent_name"),
                "callto": md.get("callto") or md.get("call_to") or md.get("to"),
                "starttime": started.isoformat() if started else None,
                "answeredtime": md.get("answeredtime") or r.get("duration_seconds"),
                "dialstatus": md.get("dialstatus") or r.get("status"),
                "direction": md.get("direction"),
            }
        )

    return Response(
        {"success": True, "data": out, "total": total, "limit": limit, "offset": offset}
    )


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def call_history(request):
    legacy = _resolve_legacy(request)
    if not legacy or legacy.get("business_id") is None:
        return Response(
            {"success": False, "data": {"conversations": [], "total": 0}, "message": "No business profile"},
            status=400,
        )
    limit = _parse_int(request.query_params, "limit", 100, min_v=1, max_v=500)
    offset = _parse_int(request.query_params, "offset", 0, min_v=0, max_v=1_000_000)
    conversations, total = fetch_call_history_page(
        legacy,
        limit=limit,
        offset=offset,
        start_date=(request.query_params.get("start_date") or "").strip() or None,
        end_date=(request.query_params.get("end_date") or "").strip() or None,
        agent_id=(request.query_params.get("agent_id") or "").strip() or None,
        customer_number=(request.query_params.get("customer_number") or "").strip() or None,
        campaign_id=(request.query_params.get("campaign_id") or "").strip() or None,
        conversation_id=(request.query_params.get("conversation_id") or "").strip() or None,
    )
    return Response(
        {
            "success": True,
            "data": {"conversations": conversations, "total": total},
        }
    )


def _stream_payload(user, date_from: str | None, date_to: str | None) -> dict[str, Any]:
    legacy = _legacy_profile_for_user(user)
    if not legacy or legacy.get("business_id") is None:
        return {"stats": None, "charts": []}
    return {
        "stats": fetch_dashboard_stats(legacy),
        "charts": fetch_dashboard_charts(legacy, date_from, date_to),
    }


def dashboard_stream(request):
    """SSE: `event: dashboard` with JSON payload. Token passed as query param (EventSource)."""
    if request.method != "GET":
        return HttpResponseForbidden("Method not allowed")
    token_key = (request.GET.get("token") or "").strip()
    if not token_key:
        return HttpResponseForbidden("missing token")
    try:
        tok = Token.objects.select_related("user").get(key=token_key)
    except Token.DoesNotExist:
        return HttpResponseForbidden("invalid token")

    user = tok.user
    date_from = (request.GET.get("date_from") or "").strip() or None
    date_to = (request.GET.get("date_to") or "").strip() or None
    try:
        interval = int(request.GET.get("interval") or 10)
    except ValueError:
        interval = 10
    interval = max(2, min(interval, 60))

    def event_generator():
        try:
            while True:
                payload = _stream_payload(user, date_from, date_to)
                yield f"event: dashboard\ndata: {json.dumps(payload)}\n\n"
                time.sleep(interval)
        except GeneratorExit:
            return

    resp = StreamingHttpResponse(
        event_generator(),
        content_type="text/event-stream",
    )
    resp["Cache-Control"] = "no-cache"
    resp["X-Accel-Buffering"] = "no"
    return resp


_EMPTY_POST_CALL = {
    "overview": {
        "totalCalls": 0,
        "completedCalls": 0,
        "analyzedCalls": 0,
        "avgHandlingTime": 0,
        "satisfactionScore": 0,
        "intentAccuracy": 0,
        "intentBreakdown": {
            "High": {"count": 0, "percentage": 0},
            "Medium": {"count": 0, "percentage": 0},
            "Low": {"count": 0, "percentage": 0},
        },
    },
    "performance": {"completionRate": 0},
}


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def post_call_analytics(request):
    return Response(_EMPTY_POST_CALL)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_transfer_reasons(request):
    return Response([])


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_sentiment(request):
    return Response([])


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_trends(request):
    return Response([])


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_bots_stats(request):
    return Response([])


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_call_volume_heatmap(request):
    return Response({"success": True, "data": {}})


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def analytics_agent_comparison(request):
    return Response([])
