#!/usr/bin/env python3
"""RabbitMQ consumer: run analytics after STT (status 2 → 3)."""

from __future__ import annotations

import json
import logging
import os
import sys
import time

import pika
from dotenv import load_dotenv

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE_DIR)

load_dotenv(os.path.join(BASE_DIR, ".env"))

from analytics_queue import analytics_queue_name
from config import Config
from db_handler import DatabaseHandler

logging.basicConfig(
    level=getattr(logging, os.getenv("LOG_LEVEL", "INFO").upper(), logging.INFO),
    format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger("analytics_worker")


class ConfigWrapper:
    def __init__(self, config):
        self._config = config

    def get(self, key, default=None):
        return getattr(self._config, key, default)

    def __getattr__(self, key):
        return getattr(self._config, key)


def _db() -> DatabaseHandler:
    cfg = ConfigWrapper(Config())
    return DatabaseHandler(cfg)


def _already_analyzed(db: DatabaseHandler, bid: str, call_id: str) -> bool:
    bid = str(bid).strip()
    call_id = str(call_id).strip()
    table = f"{bid}_raw_calls"
    analytics_table = f"{bid}_callanalytics"
    try:
        with db.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(
                f"SELECT status FROM `{table}` WHERE callid = %s LIMIT 1",
                (call_id,),
            )
            row = cursor.fetchone()
            if row and int(row.get("status") or 0) == 3:
                return True
            cursor.execute(
                f"SELECT id FROM `{analytics_table}` WHERE callid = %s LIMIT 1",
                (call_id,),
            )
            return cursor.fetchone() is not None
    except Exception as exc:
        logger.warning("[%s/%s] Could not check analyzed state: %s", bid, call_id, exc)
        return False


def process_analytics_job(bid: str, call_id: str) -> bool:
    from orchestrate_pipeline import Orchestrator

    bid = str(bid).strip()
    call_id = str(call_id).strip()
    db = _db()
    if _already_analyzed(db, bid, call_id):
        logger.info("[%s/%s] Already analyzed — skip", bid, call_id)
        return True
    orch = Orchestrator(bid)
    if not orch.analytics_enabled:
        logger.info("[%s/%s] Analytics disabled for BID", bid, call_id)
        return True
    return bool(orch.trigger_analytics(call_id))


def run_worker() -> None:
    host = os.getenv("RABBITMQ_HOST", "localhost")
    port = int(os.getenv("RABBITMQ_PORT", "5672"))
    user = os.getenv("RABBITMQ_USER", "guest")
    password = os.getenv("RABBITMQ_PASSWORD", "guest")
    queue = analytics_queue_name()

    while True:
        try:
            connection = pika.BlockingConnection(
                pika.ConnectionParameters(
                    host=host,
                    port=port,
                    credentials=pika.PlainCredentials(user, password),
                    heartbeat=600,
                )
            )
            channel = connection.channel()
            channel.queue_declare(queue=queue, durable=True)
            channel.basic_qos(prefetch_count=1)

            def _callback(ch, method, _props, body):
                bid = ""
                call_id = ""
                try:
                    data = json.loads(body.decode("utf-8"))
                    bid = str(data.get("bid") or "").strip()
                    call_id = str(data.get("call_id") or data.get("callid") or "").strip()
                    if not bid or not call_id:
                        logger.warning("Invalid analytics job payload: %s", body[:200])
                        ch.basic_ack(delivery_tag=method.delivery_tag)
                        return
                    ok = process_analytics_job(bid, call_id)
                    if ok:
                        ch.basic_ack(delivery_tag=method.delivery_tag)
                    else:
                        ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True)
                except Exception as exc:
                    logger.exception("[%s/%s] Analytics job failed: %s", bid, call_id, exc)
                    ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True)

            channel.basic_consume(queue=queue, on_message_callback=_callback)
            logger.info("Analytics worker listening on %s", queue)
            channel.start_consuming()
        except KeyboardInterrupt:
            logger.info("Analytics worker shutting down")
            break
        except Exception as exc:
            logger.exception("Analytics worker connection lost, retry in 5s: %s", exc)
            time.sleep(5)


if __name__ == "__main__":
    run_worker()
