"""
CRM Gap Analysis API - Scan Salesforce for missing contact/lead fields.

POST-V1: This feature is SHELVED for V1 launch.

Status: Gap analysis works (scans SFDC and identifies missing fields), but enrichment
execution and writeback are incomplete.

Decision: Backend kept functional. Frontend menu hidden. Can be completed post-V1.

See also:
- frontend/matching_app/src/pages/Salesforce/CrmAppend.jsx (UI)
- src/fmatch/saas/workers/crm_gap_scanner.py (worker)
- src/fmatch/saas/api/v2/contact_enrichment.py (enrichment endpoints)
"""

from __future__ import annotations

import json
import logging
from typing import Any, Dict, List, Optional

from anyio.to_thread import run_sync
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field
from rq import Queue
from sqlalchemy.ext.asyncio import AsyncSession

from ...auth import get_current_account, get_current_user
from ...db import get_session
from ...models import Job, JobStatus, JobType
from ...worker import conn as _rq_conn
from ..progress import get_redis

log = logging.getLogger("fmatch.api.crm_gap_analysis")

router = APIRouter(prefix="/api/v2/crm-append", tags=["crm-append"])


class AnalyzeGapsRequest(BaseModel):
    object_types: List[str] = Field(default_factory=lambda: ["Contact", "Lead"])
    fields: List[str] = Field(default_factory=lambda: ["Email", "MobilePhone"])
    record_limit: Optional[int] = Field(
        default=None, ge=100, le=20000, description="Maximum records per object to scan"
    )
    detail_limit: Optional[int] = Field(
        default=None,
        ge=100,
        le=5000,
        description="Maximum detail rows returned to the client",
    )


class AnalyzeGapsResponse(BaseModel):
    job_id: str
    status: str


class GapAnalysisResponse(BaseModel):
    job_id: str
    status: str
    progress: Optional[int] = 0
    message: Optional[str] = None
    summary: Optional[Dict[str, Any]] = None
    details: Optional[List[Dict[str, Any]]] = None
    updated_at: Optional[str] = None


@router.post(
    "/analyze-gaps",
    response_model=AnalyzeGapsResponse,
    status_code=status.HTTP_202_ACCEPTED,
)
async def analyze_gap_analysis(
    body: AnalyzeGapsRequest,
    db: AsyncSession = Depends(get_session),
    account_id: str = Depends(get_current_account),
    user_id: str = Depends(get_current_user),
):
    """
    Queue a CRM gap analysis job that scans Salesforce for missing contact/lead fields.
    """
    job = Job(
        account_id=str(account_id),
        status=JobStatus.QUEUED,
        job_type=JobType.CRM_GAP_ANALYSIS,
        config={
            "workflow": "crm_gap_analysis",
            "account_id": str(account_id),
            "user_id": str(user_id) if user_id else None,
            "object_types": body.object_types,
            "fields": body.fields,
            "record_limit": body.record_limit,
            "detail_limit": body.detail_limit,
        },
    )

    db.add(job)
    await db.commit()
    await db.refresh(job)

    async def _enqueue() -> None:
        def _do_enqueue():
            Queue("default", connection=_rq_conn).enqueue(
                "fmatch.saas.workers.crm_gap_scanner.run_gap_analysis_job",
                str(job.id),
                job_timeout=3600,
            )

        await run_sync(_do_enqueue)

    try:
        await _enqueue()
    except Exception as exc:
        log.error("Failed to enqueue CRM gap analysis job %s: %s", job.id, exc)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to enqueue CRM gap analysis job.",
        ) from exc

    return AnalyzeGapsResponse(job_id=str(job.id), status=job.status.value)


@router.get("/gaps/{job_id}", response_model=GapAnalysisResponse)
async def get_gap_analysis_results(
    job_id: str,
    db: AsyncSession = Depends(get_session),
    account_id: str = Depends(get_current_account),
):
    """
    Retrieve the latest results for a CRM gap analysis job.
    """
    job = await db.get(Job, job_id)
    if not job or (job.account_id and str(job.account_id) != str(account_id)):
        raise HTTPException(status.HTTP_404_NOT_FOUND, "job not found")

    try:
        redis_conn = await get_redis()
    except Exception:
        redis_conn = None

    metadata: Dict[str, Any] = {}
    if redis_conn:
        raw = await redis_conn.get(f"job:{job_id}")
        if raw:
            try:
                if isinstance(raw, bytes):
                    raw = raw.decode("utf-8")
                metadata = json.loads(raw)
            except Exception:
                metadata = {}

    summary = None
    details = None
    if isinstance(job.results, dict):
        summary = job.results.get("summary")
        details = job.results.get("details")

    status_value = job.status.value if hasattr(job.status, "value") else str(job.status)

    response = GapAnalysisResponse(
        job_id=str(job.id),
        status=status_value,
        progress=int(metadata.get("progress", 0))
        if metadata.get("progress") is not None
        else None,
        message=metadata.get("message"),
        summary=summary,
        details=details,
        updated_at=metadata.get("updated_at"),
    )
    return response
