from __future__ import annotations

from typing import Dict, Any
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from ..model_defs.c2a_models import C2ASuggestion
from ..intelligence.decision_logger import DecisionLogger
from .metrics import metrics


class ApprovalsService:
    def __init__(self, db: AsyncSession):
        self.db = db
        self.logger = DecisionLogger()

    async def fetch_pending(
        self, account_id: str, limit: int, offset: int
    ) -> Dict[str, Any]:
        q = (
            select(C2ASuggestion)
            .where(
                C2ASuggestion.account_id == str(account_id),
                C2ASuggestion.status == "pending",
            )
            .order_by(C2ASuggestion.created_at.desc())
            .offset(int(offset or 0))
            .limit(int(limit or 50))
        )
        rows = (await self.db.execute(q)).scalars().all()
        # Optional total count for pagination UI
        total_q = (
            select(func.count())
            .select_from(C2ASuggestion)
            .where(
                C2ASuggestion.account_id == str(account_id),
                C2ASuggestion.status == "pending",
            )
        )
        total = (await self.db.execute(total_q)).scalar_one()
        return {
            "items": [self._row_to_dict(r) for r in rows],
            "limit": int(limit or 50),
            "offset": int(offset or 0),
            "total": int(total or 0),
        }

    async def approve(
        self, account_id: str, suggestion_id: str, user_id: str
    ) -> Dict[str, Any]:
        r = await self.db.get(C2ASuggestion, suggestion_id)
        if not r or str(r.account_id) != str(account_id):
            raise ValueError("Not found")
        r.status = "approved"
        await self.db.commit()
        try:
            await self.logger.log_feedback(
                job_id=getattr(r, "job_id", ""),
                match_id=r.id,
                outcome="accepted",
                user_id=str(user_id),
            )
            await metrics.increment("approvals")
        except Exception:
            pass
        return {"ok": True}

    async def reject(
        self, account_id: str, suggestion_id: str, user_id: str
    ) -> Dict[str, Any]:
        r = await self.db.get(C2ASuggestion, suggestion_id)
        if not r or str(r.account_id) != str(account_id):
            raise ValueError("Not found")
        r.status = "rejected"
        await self.db.commit()
        try:
            await self.logger.log_feedback(
                job_id=getattr(r, "job_id", ""),
                match_id=r.id,
                outcome="reverted",
                user_id=str(user_id),
            )
            await metrics.increment("reverts")
        except Exception:
            pass
        return {"ok": True}

    def _row_to_dict(self, r: C2ASuggestion) -> Dict[str, Any]:
        return {
            "id": r.id,
            "contact_id": r.contact_id,
            "account_id": r.account_id,
            "score": r.score,
            "tier": (r.tier or "").lower() if r.tier else None,
            "field_score_details": r.field_score_details or {},
            "reasons": r.reasons or {},
            "created_at": getattr(r, "created_at", None),
        }
