"""Cleanup utilities.

`rescan_distribuicao_matches` re-evaluates every existing distribuicao row
against the current (strict) matching rule and deletes rows whose stored
parties don't actually identify a monitored company. Useful after tightening
the matcher — wipes homónimo false positives without a full re-scrape.
"""
import logging
from typing import Any

from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession

from app.scrapers.distribuicao import is_company_party, short_search_term

logger = logging.getLogger(__name__)


async def rescan_distribuicao_matches(session: AsyncSession) -> dict[str, int]:
    """Delete distribuicao processes whose parties don't confirm the monitored
    company under the strict (distintivo + corp suffix) rule.

    Returns a summary dict with counts per company and total deleted.
    """
    # Map company_id -> (legal_name, distinctive token)
    companies = (
        await session.execute(
            text(
                """
                SELECT id::text, legal_name
                FROM companies
                WHERE monitoring_type IN ('internal','competitor')
                """
            )
        )
    ).all()
    company_info: dict[str, tuple[str, str]] = {}
    for cid, legal in companies:
        distintivo = short_search_term(legal)
        company_info[cid] = (legal, distintivo)

    # Fetch all distribuicao processes with their parties in one pass
    rows = (
        await session.execute(
            text(
                """
                SELECT p.id::text, p.company_id::text,
                       coalesce(string_agg(pp.name, '||'), '') AS parties_blob
                FROM processes p
                LEFT JOIN process_parties pp ON pp.process_id = p.id
                WHERE p.source = 'distribuicao'
                GROUP BY p.id, p.company_id
                """
            )
        )
    ).all()

    to_delete: list[str] = []
    kept_by_company: dict[str, int] = {}
    deleted_by_company: dict[str, int] = {}
    for pid, cid, blob in rows:
        info = company_info.get(cid)
        if not info:
            to_delete.append(pid)
            deleted_by_company["<unknown>"] = deleted_by_company.get("<unknown>", 0) + 1
            continue
        legal, distintivo = info
        if not distintivo:
            # company name too ambiguous for server filter; any legacy match
            # cannot be trusted
            to_delete.append(pid)
            deleted_by_company[legal] = deleted_by_company.get(legal, 0) + 1
            continue
        parties = [p for p in (blob or "").split("||") if p]
        if any(is_company_party(p, distintivo) for p in parties):
            kept_by_company[legal] = kept_by_company.get(legal, 0) + 1
        else:
            to_delete.append(pid)
            deleted_by_company[legal] = deleted_by_company.get(legal, 0) + 1

    total_deleted = 0
    if to_delete:
        # Chunk to avoid huge IN lists
        chunk = 1000
        for i in range(0, len(to_delete), chunk):
            batch = to_delete[i : i + chunk]
            await session.execute(
                text("DELETE FROM processes WHERE id = ANY(:ids)"),
                {"ids": batch},
            )
            total_deleted += len(batch)
        await session.commit()

    logger.info(
        "rescan_distribuicao: deleted=%d kept=%d",
        total_deleted,
        sum(kept_by_company.values()),
    )
    return {
        "total_deleted": total_deleted,
        "kept_by_company": kept_by_company,
        "deleted_by_company": deleted_by_company,
    }
