from __future__ import annotations

from datetime import datetime, timezone
from typing import Optional
from uuid import UUID

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

from src.domain.l3_registry.models import L3Candidate


class L3CandidateRepository:
    def __init__(self, db: AsyncSession):
        self.db = db

    async def get(self, candidate_id: UUID) -> Optional[L3Candidate]:
        result = await self.db.execute(select(L3Candidate).where(L3Candidate.id == candidate_id))
        return result.scalar_one_or_none()

    async def get_by_external_id(self, candidate_id: str) -> Optional[L3Candidate]:
        result = await self.db.execute(select(L3Candidate).where(L3Candidate.candidate_id == candidate_id))
        return result.scalar_one_or_none()

    async def list(self, *, status: Optional[str] = None, semantic: Optional[str] = None) -> list[L3Candidate]:
        query = select(L3Candidate).order_by(L3Candidate.created_at.desc())
        if status:
            query = query.where(L3Candidate.status == status)
        if semantic:
            query = query.where(L3Candidate.semantic == semantic)
        result = await self.db.execute(query)
        return list(result.scalars().all())

    async def create(self, **values) -> L3Candidate:
        row = L3Candidate(**values)
        self.db.add(row)
        await self.db.flush()
        await self.db.refresh(row)
        return row

    async def review(self, row: L3Candidate, *, status: str, reviewer_id: UUID, notes: Optional[str], related: list[str]) -> L3Candidate:
        row.status = status
        row.reviewed_by = reviewer_id
        row.reviewed_at = datetime.now(timezone.utc)
        if notes is not None:
            row.review_notes = notes
        if related:
            row.related_candidate_ids = sorted(set((row.related_candidate_ids or []) + related))
        await self.db.flush()
        await self.db.refresh(row)
        return row
