"""
ABOS AI Worker – Meeting Analyser Router
========================================
Extracts action items, generates tasks, aligns them with projects, and supports
Human-In-Loop chat verification. Connected to React and Spring Boot.
"""

from __future__ import annotations

import json
import logging
import re
from typing import Any, Dict

import httpx
from fastapi import APIRouter, HTTPException, status

from app.config import settings
from app.schemas import (
    MeetingAnalyzeRequest,
    MeetingAnalyzeResult,
    MeetingAskRequest,
    MeetingAskResponse,
)

logger = logging.getLogger(__name__)

meeting_router = APIRouter()

# Simple transient store for meeting analysis (UUID/MeetingID -> Result)
meeting_transient_store: Dict[str, MeetingAnalyzeResult] = {}

# ---------------------------------------------------------------------------
# Helper function: Fetch Projects & credentials from Spring Boot
# ---------------------------------------------------------------------------
async def fetch_projects_and_keys(tenant_id: str, auth_token: str) -> Dict[str, Any]:
    """
    Fetches the list of active projects and AI API keys from the Spring Boot ERP database.

    Raises HTTPException(502) if Spring Boot cannot be reached or returns a
    non-200 response, instead of silently substituting mock credentials and a
    canned project list (there's no DEBUG/USE_MOCKS flag in app/config.py to
    gate a deliberate mock fallback behind) — a caller has no way to tell a
    mocked result from a real one otherwise.
    """
    spring_boot_base = "http://localhost:8080"
    url = f"{spring_boot_base}/api/finance/meetings/config"
    headers = {
        "Authorization": f"Bearer {auth_token}",
        "X-Tenant-ID": tenant_id,
        "Content-Type": "application/json"
    }

    try:
        async with httpx.AsyncClient(timeout=10) as client:
            res = await client.get(url, headers=headers)
    except Exception as exc:
        logger.error("Could not fetch meeting config from Spring Boot: %s", exc)
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail=f"Could not reach Spring Boot to fetch meeting config: {exc}",
        ) from exc

    if res.status_code != 200:
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail=f"Spring Boot returned HTTP {res.status_code} fetching meeting config.",
        )

    return res.json()

# ---------------------------------------------------------------------------
# POST /meeting/analyze
# ---------------------------------------------------------------------------
@meeting_router.post(
    "/meeting/analyze",
    response_model=MeetingAnalyzeResult,
    status_code=status.HTTP_200_OK,
    summary="Analyze meeting transcription into action items and projects",
    tags=["Meeting-Analyzer"],
)
async def analyze_meeting(request: MeetingAnalyzeRequest) -> MeetingAnalyzeResult:
    """
    Takes transcription text, extracts action items (person, summary, block),
    generates tasks, and aligns them with active projects.
    """
    # 1. Fetch credentials and active projects from Spring Boot
    config = await fetch_projects_and_keys(
        tenant_id=request.tenant_id,
        auth_token=request.spring_boot_auth_token
    )

    openai_key = config.get("openai_api_key", "")
    google_key = config.get("google_api_key", "")
    active_projects = config.get("active_projects", [])

    # Resolve LLM Key (favoring OpenAI first, then Google/OpenRouter fallback)
    llm_key = openai_key or google_key

    # 2. Build prompt
    prompt = (
        "You are an advanced Meeting Assistant. Process this transcription text in two steps:\n"
        "Step 1: Extract all actionable points. For each, note who said it or who is responsible (personSpeaker), "
        "a brief summary, and the exact discussion quote (actualBlockOfDiscussion).\n"
        "Step 2: Generate formal tasks matching these action items. Match each task to one of these projects: "
        f"{', '.join(active_projects)}. If none fit, use null.\n\n"
        "Respond ONLY with a valid JSON object matching this structure:\n"
        "{\n"
        "  \"meetingId\": \"meeting-id-here\",\n"
        "  \"title\": \"Identified meeting title\",\n"
        "  \"summary\": \"Brief overview of discussed topics\",\n"
        "  \"actionItems\": [\n"
        "    {\n"
        "      \"personSpeaker\": \"John\",\n"
        "      \"summary\": \"Update database schemas\",\n"
        "      \"actualBlockOfDiscussion\": \"John said: 'I will write the SQL scripts tomorrow'\"\n"
        "    }\n"
        "  ],\n"
        "  \"generatedTasks\": [\n"
        "    {\n"
        "      \"title\": \"Update database schemas\",\n"
        "      \"description\": \"Write and run migration scripts\",\n"
        "      \"assignee\": \"John\",\n"
        "      \"priority\": \"HIGH\",\n"
        "      \"dueDateRecommendation\": \"YYYY-MM-DD\",\n"
        "      \"projectNameRef\": \"Database Migration\"\n"
        "    }\n"
        "  ]\n"
        "}"
    )

    system_message = "You are a precise JSON extractor. Respond with raw JSON only."
    user_message = f"{prompt}\n\n--- TRANSCRIPT START ---\n{request.transcript}\n--- TRANSCRIPT END ---"

    # No usable LLM key means we cannot produce a real analysis — fail closed
    # rather than returning a canned mock result the caller can't distinguish
    # from a genuine one.
    if not llm_key:
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail="No OpenAI/Google API key was supplied for this tenant — cannot analyze the meeting transcript.",
        )

    # 3. Call LLM (using OpenRouter endpoint with dynamic key)
    payload = {
        "model": "google/gemini-2.0-flash-exp:free",
        "messages": [
            {"role": "system", "content": system_message},
            {"role": "user", "content": user_message}
        ],
        "temperature": 0.2,
        "response_format": {"type": "json_object"}
    }

    try:
        headers = {
            "Authorization": f"Bearer {llm_key}",
            "Content-Type": "application/json"
        }
        async with httpx.AsyncClient(timeout=60) as client:
            res = await client.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload)
            if res.status_code == 200:
                content = res.json()["choices"][0]["message"]["content"]
                # Clean markdown fences
                match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", content, re.IGNORECASE)
                cleaned = match.group(1).strip() if match else content.strip()
                
                parsed_data = json.loads(cleaned)
                parsed_data["meetingId"] = request.meeting_id
                
                result = MeetingAnalyzeResult.model_validate(parsed_data)
                meeting_transient_store[request.meeting_id] = result
                return result
    except Exception as exc:
        logger.error("Failed to analyze transcript via LLM: %s", exc)

    raise HTTPException(
        status_code=status.HTTP_502_BAD_GATEWAY,
        detail="Meeting analysis failed due to LLM provider issues."
    )

# ---------------------------------------------------------------------------
# POST /meeting/ask
# ---------------------------------------------------------------------------
@meeting_router.post(
    "/meeting/ask",
    response_model=MeetingAskResponse,
    status_code=status.HTTP_200_OK,
    summary="Ask questions about the transcription (HITL feature)",
    tags=["Meeting-Analyzer"],
)
async def ask_about_meeting(request: MeetingAskRequest) -> MeetingAskResponse:
    """
    Processes a direct user question regarding the meeting content/transcript.
    """
    config = await fetch_projects_and_keys(
        tenant_id=request.tenant_id,
        auth_token=request.spring_boot_auth_token
    )
    llm_key = config.get("openai_api_key", "") or config.get("google_api_key", "")
    if not llm_key:
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail="No OpenAI/Google API key was supplied for this tenant — cannot answer meeting questions.",
        )

    prompt = (
        f"Answer this user question referencing the meeting transcript below.\n"
        f"Question: {request.question}\n\n"
        f"--- TRANSCRIPT START ---\n{request.transcript}\n--- TRANSCRIPT END ---\n"
        f"Answer:"
    )

    payload = {
        "model": "google/gemini-2.0-flash-exp:free",
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.5
    }

    try:
        headers = {
            "Authorization": f"Bearer {llm_key}",
            "Content-Type": "application/json"
        }
        async with httpx.AsyncClient(timeout=30) as client:
            res = await client.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload)
            if res.status_code == 200:
                answer = res.json()["choices"][0]["message"]["content"].strip()
                return MeetingAskResponse(
                    meetingId=request.meeting_id,
                    question=request.question,
                    answer=answer
                )
    except Exception as exc:
        logger.error("Chat question failed: %s", exc)

    raise HTTPException(
        status_code=status.HTTP_502_BAD_GATEWAY,
        detail="Meeting query failed."
    )

# ---------------------------------------------------------------------------
# POST /meeting/verify
# ---------------------------------------------------------------------------
@meeting_router.post(
    "/meeting/verify",
    status_code=status.HTTP_200_OK,
    summary="Submit human-verified meeting items and save to Spring Boot",
    tags=["Meeting-Analyzer"],
)
async def verify_meeting_items(
    body: MeetingAnalyzeResult,
    spring_boot_url: str,
    auth_token: str,
    tenant_id: str
) -> Dict[str, str]:
    """
    Submits verified Tasks and Action Items to Spring Boot to create Projects/Tasks.
    """
    headers = {
        "Authorization": f"Bearer {auth_token}",
        "X-Tenant-ID": tenant_id,
        "Content-Type": "application/json"
    }

    # Post finalized JSON data back to Core Spring Boot ERP
    payload = body.model_dump(by_alias=True, mode="json")
    
    try:
        async with httpx.AsyncClient(timeout=20) as client:
            response = await client.post(
                f"{spring_boot_url}/api/finance/meetings/finalize",
                headers=headers,
                json=payload
            )
            response.raise_for_status()
    except Exception as exc:
        logger.error("Finalizing tasks in Spring Boot failed: %s", exc)
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail=f"Failed to save verified tasks to Spring Boot: {exc}"
        )

    # Evict transient record
    meeting_transient_store.pop(body.meeting_id, None)

    return {"status": "SUCCESS", "message": "Meeting items finalized and tasks loaded into projects."}
