"""Unassigned inbound leads/contacts check."""

from __future__ import annotations

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

from .base import BaseScoutCheck
from ..crm_provider import Filter, FilterExpr, FilterOp, OrGroup
from ..models import EvidenceRow, RecommendedAction, ScoutFinding


class UnassignedInboundCheck(BaseScoutCheck):
    def build_count_filters(self) -> Tuple[str, List[FilterExpr]]:
        return "lead", []

    def build_sample_request(self) -> Tuple[str, List[str], List[FilterExpr], str | None, str, bool]:
        return "lead", ["Id"], [], None, "ASC", False

    def evaluate(self, rows: List[Dict[str, Any]]) -> List[EvidenceRow]:
        return []

    def execute(self) -> ScoutFinding:  # type: ignore[override]
        start = time.perf_counter()
        evidence: List[EvidenceRow] = []
        total_scanned = 0

        lookback_days = int(self.params.get("lookback_days", 3))
        sobjects = self.params.get("sobjects", ["Lead"]) or ["Lead"]
        sobjects = [str(s).lower() for s in sobjects]
        queue_ids = [str(q) for q in (self.params.get("queue_ids", []) or [])]
        queue_name_map: Dict[str, str] = {}

        if self.provider.name == "salesforce":
            if not queue_ids:
                try:
                    group_rows = self.provider.query(
                        "group",
                        ["Id", "Name", "Type"],
                        [Filter("Type", FilterOp.EQ, "Queue")],
                        limit=500,
                    )
                    self._collect_provider_meta()
                    queue_ids = [row.get("Id", "") for row in group_rows if row.get("Id")]
                    for row in group_rows:
                        gid = row.get("Id")
                        if gid:
                            queue_name_map[gid] = row.get("Name") or gid
                except Exception as exc:
                    self._warnings.append(f"Queue lookup failed: {exc}")

        for obj in sobjects:
            if not self.provider.supports_object(obj):
                self._warnings.append(f"Unsupported object: {obj}")
                continue

            filters: List[FilterExpr] = [Filter("CreatedDate", FilterOp.LAST_N_DAYS, lookback_days)]
            owner_filters: List[FilterExpr] = [Filter("OwnerId", FilterOp.IS_NULL)]
            if self.provider.name == "salesforce" and queue_ids:
                owner_filters.append(Filter("OwnerId", FilterOp.IN, queue_ids))
            filters.append(OrGroup(filters=owner_filters))

            count = self.provider.count(obj, filters)
            self._collect_provider_meta()
            total_scanned += count

            rows = self.provider.query(
                obj,
                ["Id", "Name", "Email", "CreatedDate", "OwnerId"],
                filters,
                order_by="CreatedDate",
                order_dir="ASC",
                limit=self.top_n,
            )
            self._collect_provider_meta()

            for row in rows:
                record_id = row.get("Id", "")
                if not record_id:
                    continue
                owner_id = row.get("OwnerId")
                if owner_id and owner_id in queue_ids:
                    reason_code = "QUEUE_OWNED"
                    reason = f"Record owned by queue {queue_name_map.get(owner_id, owner_id)}"
                else:
                    reason_code = "NO_OWNER"
                    reason = "Record has no owner"
                evidence.append(
                    EvidenceRow(
                        record_id=record_id,
                        sobject=obj,
                        fields={
                            "Name": row.get("Name"),
                            "Email": row.get("Email"),
                            "CreatedDate": row.get("CreatedDate"),
                            "OwnerId": owner_id,
                            "queue_name": queue_name_map.get(owner_id, "") if owner_id else "",
                        },
                        reason=reason,
                        reason_code=reason_code,
                        severity=self.definition.severity_default,
                    )
                )

        total_findings = len(evidence)
        if len(evidence) > self.top_n:
            evidence = evidence[: self.top_n]

        status = "findings" if total_findings > 0 else "ok"
        duration_ms = int((time.perf_counter() - start) * 1000)
        return ScoutFinding(
            scout_name=self.definition.name,
            display_name=self.definition.display_name,
            description=self.definition.description,
            category=self.definition.category,
            severity=self.definition.severity_default,
            total_records_scanned=total_scanned,
            findings_count=total_findings,
            evidence=evidence,
            recommended_actions=self.get_recommended_actions(),
            soql_queries=self._soql_queries,
            duration_ms=duration_ms,
            parameters_used=self.params,
            status=status,
            warnings=self._warnings,
        )

    def get_recommended_actions(self) -> List[RecommendedAction]:
        return [
            RecommendedAction(
                action_type="create_task",
                label="Create assignment tasks",
                risk_level="low",
            ),
            RecommendedAction(
                action_type="flag_record",
                label="Flag unassigned inbound records",
                risk_level="low",
            ),
            RecommendedAction(
                action_type="export_csv",
                label="Export unassigned inbound records",
                risk_level="safe",
            ),
        ]


__all__ = ["UnassignedInboundCheck"]
