"""Tag review service for HITL workflow (Phase 4).

Handles confirm/reject operations for pending tags per Spec Section 4.3.
"""

import time
from typing import Optional
from uuid import UUID

import structlog
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from src.api.schemas.tags import TagHistoryEntry, TagReviewDecision, TagStatus
from src.db.models import ExtractedRecord

logger = structlog.get_logger(__name__)


class TagReviewService:
    """Service for reviewing and managing tag verification workflow.

    Phase 4 Enhancement: Implements HITL workflow per Spec Section 4.3.
    """

    def __init__(self, session: AsyncSession):
        """Initialize tag review service.

        Args:
            session: Database session
        """
        self.session = session
        self.logger = structlog.get_logger(__name__)

    async def get_record_tags(self, record_id: UUID) -> Optional[dict]:
        """Get all tags for a record with metadata.

        Args:
            record_id: Record UUID

        Returns:
            Dict with record_id and tags list, or None if not found
        """
        stmt = select(ExtractedRecord).where(ExtractedRecord.id == record_id)
        result = await self.session.execute(stmt)
        record = result.scalar_one_or_none()

        if not record:
            return None

        return {"record_id": record_id, "tags": record.tags or []}

    async def review_tag(
        self,
        record_id: UUID,
        tag_id: str,
        decision: TagReviewDecision,
        reviewer: str = "user",
        reason: Optional[str] = None,
    ) -> tuple[bool, Optional[str]]:
        """Review a pending tag (confirm or reject).

        Args:
            record_id: Record UUID
            tag_id: Tag UUID to review
            decision: Confirm or reject
            reviewer: User ID or identifier
            reason: Optional reason for rejection

        Returns:
            Tuple of (success, error_message)

        Note:
            Updates tag status and history in-place per Spec Section 4.3.1.
        """
        # Fetch record
        stmt = select(ExtractedRecord).where(ExtractedRecord.id == record_id)
        result = await self.session.execute(stmt)
        record = result.scalar_one_or_none()

        if not record:
            return False, "record_not_found"

        tags = record.tags or []

        # Find tag by ID
        tag_index = None
        for idx, tag in enumerate(tags):
            if tag.get("tag_id") == tag_id:
                tag_index = idx
                break

        if tag_index is None:
            return False, "tag_not_found"

        tag = tags[tag_index]

        # Check if already reviewed
        current_status = tag.get("status")
        if current_status == "verified":
            return False, "tag_already_verified"
        if current_status == "rejected":
            return False, "tag_already_rejected"

        # Apply decision
        current_ts = int(time.time())

        if decision == TagReviewDecision.CONFIRM:
            # Confirm tag
            tag["status"] = TagStatus.VERIFIED.value
            tag["source"] = "human"  # Human verification overrides AI
            tag["confidence"] = 1.0  # Human verification = 100% confidence

            # Add history entry
            if "history" not in tag:
                tag["history"] = []
            tag["history"].append(
                {
                    "action": "confirmed",
                    "by": reviewer,
                    "ts": current_ts,
                }
            )

            self.logger.info(
                "tag_confirmed",
                record_id=str(record_id),
                tag_id=tag_id,
                tag_name=tag.get("name"),
                reviewer=reviewer,
            )

        elif decision == TagReviewDecision.REJECT:
            # Reject tag
            tag["status"] = TagStatus.REJECTED.value

            # Add history entry with reason
            if "history" not in tag:
                tag["history"] = []
            history_entry = {
                "action": "rejected",
                "by": reviewer,
                "ts": current_ts,
            }
            if reason:
                history_entry["reason"] = reason

            tag["history"].append(history_entry)

            self.logger.info(
                "tag_rejected",
                record_id=str(record_id),
                tag_id=tag_id,
                tag_name=tag.get("name"),
                reviewer=reviewer,
                reason=reason,
            )

        # Update record tags
        record.tags = tags
        await self.session.commit()

        return True, None

    async def get_pending_tags_count(
        self, record_id: Optional[UUID] = None
    ) -> dict[str, int]:
        """Get count of pending tags.

        Args:
            record_id: Optional record ID to filter by

        Returns:
            Dict with counts by status
        """
        # For now, return a simple count
        # In production, this would be a more complex query
        if record_id:
            stmt = select(ExtractedRecord).where(ExtractedRecord.id == record_id)
            result = await self.session.execute(stmt)
            record = result.scalar_one_or_none()

            if not record:
                return {"pending": 0, "verified": 0, "rejected": 0}

            tags = record.tags or []
            counts = {"pending": 0, "verified": 0, "rejected": 0}

            for tag in tags:
                status = tag.get("status", "pending")
                counts[status] = counts.get(status, 0) + 1

            return counts

        # Global count would require more complex aggregation
        return {"pending": 0, "verified": 0, "rejected": 0}
