from __future__ import annotations

from typing import Any, Protocol

from .models import DocumentResult, EvidenceValue


class DocumentAdapter(Protocol):
    def adapt(self, documents: list[dict[str, Any]], current_day: int = 50) -> DocumentResult: ...


class OfflineDocumentAdapter:
    required = {"subject_ref", "amount_units", "currency_code", "submitted_day"}
    allowed_currency = {"UNIT-A", "UNIT-B"}

    def adapt(self, documents: list[dict[str, Any]], current_day: int = 50) -> DocumentResult:
        result = DocumentResult()
        candidates: dict[str, list[EvidenceValue]] = {}
        for document in documents:
            if document.get("instruction"):
                result.untrusted_instructions += 1
            doc_id = str(document.get("document_id", "unknown"))
            for name, entry in document.get("fields", {}).items():
                if not isinstance(entry, dict) or set(entry) - {"value", "location", "readable"}:
                    result.problems.append({"kind": "STRUCTURE", "field": name, "evidence": doc_id})
                    continue
                if not entry.get("readable", True):
                    result.problems.append({"kind": "UNREADABLE", "field": name, "evidence": f"{doc_id}:{entry.get('location','?')}"})
                    continue
                candidates.setdefault(name, []).append(EvidenceValue(entry.get("value"), doc_id, str(entry.get("location", "?"))))
        for name in self.required:
            values = candidates.get(name, [])
            if not values:
                result.problems.append({"kind": "MISSING", "field": name, "evidence": []})
            elif len({str(item.value) for item in values}) > 1:
                result.problems.append({"kind": "CONFLICT", "field": name, "evidence": [f"{item.document_id}:{item.location}" for item in values]})
            else:
                result.fields[name] = values[0]
        if "amount_units" in result.fields and not isinstance(result.fields["amount_units"].value, int):
            result.problems.append({"kind": "UNIT_MISMATCH", "field": "amount_units", "evidence": result.fields["amount_units"].location})
        if "currency_code" in result.fields and result.fields["currency_code"].value not in self.allowed_currency:
            result.problems.append({"kind": "UNIT_MISMATCH", "field": "currency_code", "evidence": result.fields["currency_code"].location})
        if "submitted_day" in result.fields:
            day = result.fields["submitted_day"].value
            if not isinstance(day, int):
                result.problems.append({"kind": "DATE_INVALID", "field": "submitted_day", "evidence": result.fields["submitted_day"].location})
            elif current_day - day > 30:
                result.problems.append({"kind": "STALE", "field": "submitted_day", "evidence": result.fields["submitted_day"].location})
        return result

