"""Post-actions after Sarvam key update: restart STT, ensure orchestrators, retry failures."""
from __future__ import annotations

import logging
from typing import Any, Dict, Sequence

from error_call_retry_util import build_retry_update_sets, columns_for_error_retry, queue_calls_for_stt

logger = logging.getLogger(__name__)


def _table_exists(cursor, table_name: str) -> bool:
    cursor.execute(
        """
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = DATABASE() AND table_name = %s
        LIMIT 1
        """,
        (table_name,),
    )
    return cursor.fetchone() is not None


def _existing_table_columns(cursor, table_name: str) -> set:
    cursor.execute(
        """
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = DATABASE() AND table_name = %s
        """,
        (table_name,),
    )
    return {str(r.get("column_name") or r.get("COLUMN_NAME") or "") for r in (cursor.fetchall() or [])}


def retry_stt_failed_for_bids(
    bids: Sequence[str],
    *,
    db_conn_factory,
    max_per_bid: int = 300,
) -> Dict[str, Any]:
    """Reset status=-2 calls and queue them for STT (pipeline-enabled BIDs only)."""
    summary: Dict[str, Any] = {
        "bids_checked": 0,
        "bids_with_failures": 0,
        "retried_total": 0,
        "queued_total": 0,
        "skipped_usage_total": 0,
        "per_bid": [],
    }
    limit = max(1, int(max_per_bid))

    for bid in bids:
        bid = str(bid or "").strip()
        if not bid:
            continue
        summary["bids_checked"] += 1
        table = f"{bid}_raw_calls"
        bid_stats = {
            "bid": bid,
            "stt_failed_found": 0,
            "retried": 0,
            "queued": 0,
            "skipped_usage": 0,
        }

        with db_conn_factory() as conn:
            with conn.cursor() as cursor:
                if not _table_exists(cursor, table):
                    summary["per_bid"].append(bid_stats)
                    continue

                cursor.execute(f"SELECT COUNT(*) AS c FROM `{table}` WHERE status = -2")
                failed_count = int((cursor.fetchone() or {}).get("c") or 0)
                bid_stats["stt_failed_found"] = failed_count
                if failed_count < 1:
                    summary["per_bid"].append(bid_stats)
                    continue

                summary["bids_with_failures"] += 1
                existing_cols = _existing_table_columns(cursor, table)
                select_cols = ", ".join(f"`{c}`" for c in columns_for_error_retry(existing_cols))
                cursor.execute(
                    f"""
                    SELECT {select_cols}
                    FROM `{table}`
                    WHERE status = -2
                    ORDER BY call_starttime DESC
                    LIMIT %s
                    """,
                    (limit,),
                )
                error_rows = [dict(r) for r in (cursor.fetchall() or []) if r.get("callid")]
                if not error_rows:
                    summary["per_bid"].append(bid_stats)
                    continue

                callids = [str(r["callid"]) for r in error_rows]
                placeholders = ", ".join(["%s"] * len(callids))
                retry_sets = build_retry_update_sets(existing_cols)
                cursor.execute(
                    f"UPDATE `{table}` SET {', '.join(retry_sets)} WHERE callid IN ({placeholders})",
                    callids,
                )
                bid_stats["retried"] = int(cursor.rowcount or 0)
            conn.commit()

        if bid_stats["retried"] > 0:
            queued_stats = queue_calls_for_stt(bid, error_rows, db_conn_factory=db_conn_factory)
            bid_stats["queued"] = int(queued_stats.get("queued") or 0)
            bid_stats["skipped_usage"] = int(queued_stats.get("skipped_usage") or 0)
            summary["retried_total"] += bid_stats["retried"]
            summary["queued_total"] += bid_stats["queued"]
            summary["skipped_usage_total"] += bid_stats["skipped_usage"]

        summary["per_bid"].append(bid_stats)

    return summary


def resume_pipeline_after_sarvam_key_update(
    *,
    db_conn_factory,
    get_enabled_bids,
    retry_failed: bool = True,
    max_retry_per_bid: int = 300,
) -> Dict[str, Any]:
    """Restart STT workers, ensure orchestrator loops, optionally retry STT-failed calls."""
    result: Dict[str, Any] = {
        "stt_restart": None,
        "orchestrator_sync": None,
        "stt_retry": None,
    }

    try:
        from stt_worker_supervisor import sync_workers

        result["stt_restart"] = sync_workers(force_restart=True)
    except Exception as exc:
        logger.warning("STT worker restart after key update failed: %s", exc)
        result["stt_restart"] = {"error": str(exc)}

    try:
        from orchestrator_supervisor import sync_enabled_loops

        result["orchestrator_sync"] = sync_enabled_loops()
    except Exception as exc:
        logger.warning("Orchestrator sync after key update failed: %s", exc)
        result["orchestrator_sync"] = {"error": str(exc)}

    if retry_failed:
        try:
            bids = list(get_enabled_bids() or [])
            result["stt_retry"] = retry_stt_failed_for_bids(
                bids,
                db_conn_factory=db_conn_factory,
                max_per_bid=max_retry_per_bid,
            )
        except Exception as exc:
            logger.warning("STT failed-call retry after key update failed: %s", exc)
            result["stt_retry"] = {"error": str(exc)}

    return result
