#!/usr/bin/env python3
"""Clean stale invalid email-identity suggestions/extractions.

Use after strengthening company-mention filters.  It targets suggestions and
stored extractions created from invalid fragments such as ``pt`` or ``com``.
"""
from __future__ import annotations

import argparse
import json
from typing import Any

from sqlalchemy import text

from app.db import engine
from app.email_identity_extraction_service import is_plausible_company_mention

INVALID = {"pt", "com", "net", "org", "www", "http", "https", "mail", "email"}


def _clean(value: Any) -> str:
    return str(value or "").strip()


def _valid_companies(values: Any) -> list[str]:
    out: list[str] = []
    if not isinstance(values, list):
        return out
    for value in values:
        v = _clean(value).strip(" ,.;:-")
        if v and is_plausible_company_mention(v):
            out.append(v)
    return out


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--opportunity-id", default="")
    parser.add_argument("--apply", action="store_true")
    parser.add_argument("--include-accepted", action="store_true")
    parser.add_argument("--fix-extractions", action="store_true", help="Also rewrite stored email_identity_extractions company_mentions after current filters")
    args = parser.parse_args()

    where = ["lookup_type LIKE 'email_identity%'"]
    params: dict[str, Any] = {}
    if args.opportunity_id:
        where.append("opportunity_id = CAST(:opportunity_id AS UUID)")
        params["opportunity_id"] = args.opportunity_id
    if args.include_accepted:
        where.append("status IN ('pending', 'accepted', 'rejected')")
    else:
        where.append("status = 'pending'")
    invalid_sql = ", ".join("'" + v.replace("'", "") + "'" for v in sorted(INVALID))
    where.append(f"lower(trim(COALESCE(lookup_value, ''))) IN ({invalid_sql})")

    sql_where = " AND ".join(where)
    with engine.begin() as conn:
        rows = conn.execute(text(f"""
            SELECT id::text, opportunity_id::text, suggested_name, suggested_nif,
                   lookup_type, lookup_value, confidence, status, reason, created_at
            FROM fiscal_customer_suggestions
            WHERE {sql_where}
            ORDER BY created_at DESC
        """), params).mappings().all()

        print(json.dumps({"invalid_suggestions": len(rows), "apply": args.apply}, ensure_ascii=False, indent=2, default=str))
        for row in rows:
            print(json.dumps(dict(row), ensure_ascii=False, indent=2, default=str))

        if args.apply and rows:
            ids = [r["id"] for r in rows]
            conn.execute(text("""
                UPDATE fiscal_customer_suggestions
                SET status = 'rejected',
                    reason = COALESCE(reason, '') || ' | rejected_invalid_email_identity_token',
                    resolved_by = 'cleanup_invalid_email_identity_suggestions',
                    resolved_at = now(),
                    updated_at = now()
                WHERE id = ANY(CAST(:ids AS UUID[]))
            """), {"ids": ids})
            print(json.dumps({"rejected": len(ids)}, ensure_ascii=False, indent=2))

        if args.fix_extractions:
            extraction_where = []
            extraction_params: dict[str, Any] = {}
            if args.opportunity_id:
                extraction_where.append("opportunity_id = CAST(:opportunity_id AS UUID)")
                extraction_params["opportunity_id"] = args.opportunity_id
            extraction_sql = "WHERE " + " AND ".join(extraction_where) if extraction_where else ""
            ex_rows = conn.execute(text(f"""
                SELECT id::text, opportunity_id::text, company_mentions, confidence, raw_payload
                FROM email_identity_extractions
                {extraction_sql}
                ORDER BY updated_at DESC
            """), extraction_params).mappings().all()
            changed = []
            for row in ex_rows:
                original = row.get("company_mentions") or []
                valid = _valid_companies(original)
                if list(original or []) == valid:
                    continue
                changed.append({"id": row["id"], "opportunity_id": row["opportunity_id"], "before": original, "after": valid})
                if args.apply:
                    try:
                        confidence = float(row.get("confidence") or 0)
                    except Exception:
                        confidence = 0.0
                    if not valid:
                        confidence = min(confidence, 0.45)
                    raw_payload = dict(row.get("raw_payload") or {}) if isinstance(row.get("raw_payload"), dict) else {}
                    raw_payload["filtered_invalid_company_mentions"] = list(original or [])
                    conn.execute(text("""
                        UPDATE email_identity_extractions
                        SET company_mentions = CAST(:company_mentions AS JSONB),
                            confidence = :confidence,
                            raw_payload = COALESCE(raw_payload, '{}'::jsonb) || CAST(:raw_payload AS JSONB),
                            updated_at = now()
                        WHERE id = CAST(:id AS UUID)
                    """), {
                        "id": row["id"],
                        "company_mentions": json.dumps(valid, ensure_ascii=False),
                        "confidence": confidence,
                        "raw_payload": json.dumps(raw_payload, ensure_ascii=False, default=str),
                    })
            print(json.dumps({"extractions_to_fix": len(changed), "items": changed}, ensure_ascii=False, indent=2, default=str))

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
