"""Lead follow-up SLA check."""

from __future__ import annotations

from typing import Any, Dict, List, Set, Tuple

from .base import BaseScoutCheck
from ..crm_provider import Filter, FilterExpr, FilterOp
from ..models import EvidenceRow, RecommendedAction
from ..utils import chunked, hours_since


class LeadFollowupCheck(BaseScoutCheck):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self._touched_ids: Set[str] = set()

    def build_count_filters(self) -> Tuple[str, List[FilterExpr]]:
        filters: List[FilterExpr] = [
            Filter("IsConverted", FilterOp.EQ, False),
            Filter("CreatedDate", FilterOp.LAST_N_DAYS, 3),
        ]
        return "lead", filters

    def build_sample_request(self) -> Tuple[str, List[str], List[FilterExpr], str | None, str, bool]:
        fields = ["Id", "Name", "OwnerId", "Email", "Company", "CreatedDate"]
        filters: List[FilterExpr] = [
            Filter("IsConverted", FilterOp.EQ, False),
            Filter("CreatedDate", FilterOp.LAST_N_DAYS, 3),
        ]
        return "lead", fields, filters, "CreatedDate", "ASC", False

    def fetch_sample_rows(self) -> List[Dict[str, Any]]:
        obj_type, fields, filters, order_by, order_dir, nulls_first = self.build_sample_request()
        leads = self.provider.query(
            obj_type,
            fields,
            filters,
            order_by=order_by,
            order_dir=order_dir,
            nulls_first=nulls_first,
            limit=self.top_n,
        )
        self._collect_provider_meta()

        lead_ids = [row.get("Id", "") for row in leads if row.get("Id")]
        if not lead_ids:
            return leads

        touched: Set[str] = set()
        for chunk in chunked(lead_ids):
            task_rows = self.provider.query(
                "task",
                ["RelatedToId"],
                [Filter("RelatedToId", FilterOp.IN, list(chunk))],
                limit=200,
            )
            for task in task_rows:
                related_id = task.get("RelatedToId") or task.get("WhoId")
                if related_id:
                    touched.add(related_id)
        self._collect_provider_meta()
        self._touched_ids = touched
        return leads

    def evaluate(self, rows: List[Dict[str, Any]]) -> List[EvidenceRow]:
        evidence: List[EvidenceRow] = []
        sla_24h = bool(self.params.get("sla_24h", True))
        sla_72h = bool(self.params.get("sla_72h", True))
        check_missing_owner = bool(self.params.get("check_missing_owner", True))

        for row in rows:
            record_id = row.get("Id", "")
            if not record_id:
                continue

            fields = {
                "Name": row.get("Name"),
                "Email": row.get("Email"),
                "Company": row.get("Company"),
                "OwnerId": row.get("OwnerId"),
                "CreatedDate": row.get("CreatedDate"),
            }

            if check_missing_owner and not row.get("OwnerId"):
                evidence.append(
                    EvidenceRow(
                        record_id=record_id,
                        sobject="lead",
                        fields=dict(fields),
                        reason="Lead missing owner",
                        reason_code="MISSING_OWNER",
                        severity=self.definition.severity_default,
                    )
                )

            if record_id in self._touched_ids:
                continue

            hours = hours_since(row.get("CreatedDate"))
            if hours is None:
                continue

            if sla_72h and hours >= 72:
                evidence.append(
                    EvidenceRow(
                        record_id=record_id,
                        sobject="lead",
                        fields=dict(fields),
                        reason=f"No follow-up in {int(hours)} hours",
                        reason_code="UNWORKED_72H",
                        severity=self.definition.severity_default,
                    )
                )
            elif sla_24h and hours >= 24:
                evidence.append(
                    EvidenceRow(
                        record_id=record_id,
                        sobject="lead",
                        fields=dict(fields),
                        reason=f"No follow-up in {int(hours)} hours",
                        reason_code="UNWORKED_24H",
                        severity=self.definition.severity_default,
                    )
                )

        return evidence

    def _findings_count(self, count: int, evidence: List[EvidenceRow]) -> int:
        if evidence and len(evidence) >= self.top_n:
            self._warnings.append(
                "Evidence capped at top_n; findings_count reflects sample size."
            )
        return len(evidence)

    def _derive_status(self, count: int, evidence: List[EvidenceRow]) -> str:
        return "findings" if evidence else "ok"

    def get_recommended_actions(self) -> List[RecommendedAction]:
        return [
            RecommendedAction(
                action_type="create_task",
                label="Create follow-up tasks for untouched leads",
                risk_level="low",
            ),
            RecommendedAction(
                action_type="flag_record",
                label="Flag leads that missed SLA",
                risk_level="low",
            ),
            RecommendedAction(
                action_type="export_csv",
                label="Export untouched leads to CSV",
                risk_level="safe",
            ),
        ]


__all__ = ["LeadFollowupCheck"]
