"""Cross-Placement-Agent — empfiehlt Footer-Reiter 'Legal' bei
deplatziertem Content.

Methodik:
  1. Findet Sektions-Headings im Impressum (Copyright, Disclaimer,
     ElektroG, …).
  2. Pro Treffer ein LOW/MEDIUM-Finding mit Best-Practice-Empfehlung
     wohin der Inhalt umziehen sollte.
  3. Rollup buendelt mehrere Treffer zu einer Master-Empfehlung
     ('Footer-Reiter \"Legal\" einfuehren').
"""

from __future__ import annotations

import logging
from datetime import datetime, timezone

from .._base import (
    AgentInput,
    AgentOutput,
    BaseSpecialistAgent,
    EvidenceSource,
    Finding,
    McCoverage,
    Severity,
    SourceType,
    lint_output,
)
from .._rollup import rollup
from .sections import SECTIONS, find_sections

logger = logging.getLogger(__name__)


_SEVERITY_FOR_CATEGORY = {
    "recommended_separate": Severity.LOW,
    "product_compliance": Severity.MEDIUM,
    "mandatory": Severity.INFO,
}


class CrossPlacementAgent(BaseSpecialistAgent):
    agent_id = "cross_placement"
    agent_version = "1.0"
    doc_type = "impressum"   # arbeitet auf Impressum-Texten
    owned_mc_ids = tuple(f"CP-PLACE-{s.section_id.upper()}"
                          for s in SECTIONS)

    async def evaluate(self, agent_input: AgentInput) -> AgentOutput:
        start = datetime.now(timezone.utc)
        text = (agent_input.text or "").strip()
        coverage: list[McCoverage] = []
        findings: list[Finding] = []

        if len(text) < 100:
            for sec in SECTIONS:
                coverage.append(McCoverage(
                    mc_id=f"CP-PLACE-{sec.section_id.upper()}",
                    status="skipped",
                    reason="text too short",
                ))
            return self._finalize(start, findings, coverage, confidence=0.0,
                                   notes="Text zu kurz für Placement-Check.")

        hits = find_sections(text)
        hit_ids = {sec.section_id for sec, _ in hits}
        for sec in SECTIONS:
            mc_id = f"CP-PLACE-{sec.section_id.upper()}"
            if sec.section_id not in hit_ids:
                coverage.append(McCoverage(
                    mc_id=mc_id, status="ok",
                    reason="section not present",
                ))
                continue
            evidence = next(s for sec2, s in hits
                              if sec2.section_id == sec.section_id)
            sev = _SEVERITY_FOR_CATEGORY.get(sec.category, Severity.LOW)
            findings.append(Finding(
                check_id=f"CROSS-PLACE-{sec.section_id.upper()}",
                agent=self.agent_id,
                agent_version=self.agent_version,
                field_id=sec.section_id,
                severity=sev,
                severity_reason="misplaced_content",
                title=(
                    f"Sektion '{sec.label}' im Impressum — empfohlene "
                    f"Platzierung: {sec.recommended_location}"
                ),
                norm=sec.norm,
                evidence=f'„{evidence}"',
                action=(
                    f"Sektion '{sec.label}' aus dem Impressum auslagern "
                    f"nach {sec.recommended_location}. Best Practice: "
                    f"einen Footer-Reiter 'Legal' einrichten, der die "
                    f"folgenden Inhalte sammelt: Copyright, Bildquellen, "
                    f"Disclaimer, Nutzungsbedingungen. Das Impressum "
                    f"bleibt schlank und enthält ausschließlich die "
                    f"Pflichtangaben nach § 5 TMG/DDG."
                ),
                confidence=0.85,
                sources=[EvidenceSource(
                    source_type=SourceType.MC,
                    source_id=mc_id,
                    detail=f"heading detected via regex",
                    confidence=0.85,
                )],
            ))
            coverage.append(McCoverage(
                mc_id=mc_id, status=sev.value.lower(),
                reason="misplaced content detected",
            ))

        confidence = 0.92 if not findings else 0.85
        return self._finalize(
            start, findings, coverage, confidence=confidence,
        )

    def _finalize(
        self,
        start: datetime,
        findings: list[Finding],
        coverage: list[McCoverage],
        confidence: float,
        notes: str = "",
    ) -> AgentOutput:
        end = datetime.now(timezone.utc)
        recs = rollup(findings)
        out = AgentOutput(
            agent=self.agent_id,
            agent_version=self.agent_version,
            started_at=start,
            finished_at=end,
            duration_ms=int((end - start).total_seconds() * 1000),
            findings=findings,
            recommendations=recs,
            mc_coverage=coverage,
            escalation_log=[],
            confidence=confidence,
            notes=notes,
            mc_total=len(coverage),
            mc_ok=sum(1 for c in coverage if c.status == "ok"),
            mc_na=sum(1 for c in coverage if c.status == "na"),
            mc_high=sum(1 for c in coverage if c.status == "high"),
            mc_medium=sum(1 for c in coverage if c.status == "medium"),
            mc_low=sum(1 for c in coverage if c.status == "low"),
        )
        return lint_output(out)
