"""People management endpoints."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import func
from sqlalchemy.orm import Session

from src.web.db.session import get_db
from src.web.db.models import Person, Face
from src.web.schemas.people import (
    PeopleListResponse,
    PersonCreateRequest,
    PersonResponse,
    PersonUpdateRequest,
    PersonWithFacesResponse,
    PeopleWithFacesListResponse,
)
from src.web.schemas.faces import PersonFacesResponse, PersonFaceItem, AcceptMatchesRequest, IdentifyFaceResponse
from src.web.services.face_service import accept_auto_match_matches

router = APIRouter(prefix="/people", tags=["people"])


@router.get("", response_model=PeopleListResponse)
def list_people(
    last_name: str | None = Query(None, description="Filter by last name (case-insensitive)"),
    db: Session = Depends(get_db),
) -> PeopleListResponse:
    """List all people sorted by last_name, first_name.
    
    Optionally filter by last_name if provided (case-insensitive search).
    """
    query = db.query(Person)
    
    if last_name:
        # Case-insensitive search on last_name
        query = query.filter(func.lower(Person.last_name).contains(func.lower(last_name)))
    
    people = query.order_by(Person.last_name.asc(), Person.first_name.asc()).all()
    items = [PersonResponse.model_validate(p) for p in people]
    return PeopleListResponse(items=items, total=len(items))


@router.get("/with-faces", response_model=PeopleWithFacesListResponse)
def list_people_with_faces(
    last_name: str | None = Query(None, description="Filter by last name or maiden name (case-insensitive)"),
    db: Session = Depends(get_db),
) -> PeopleWithFacesListResponse:
    """List all people with face counts, sorted by last_name, first_name.
    
    Optionally filter by last_name or maiden_name if provided (case-insensitive search).
    Only returns people who have at least one face.
    """
    # Query people with face counts
    query = (
        db.query(
            Person,
            func.count(Face.id).label('face_count')
        )
        .join(Face, Person.id == Face.person_id)
        .group_by(Person.id)
        .having(func.count(Face.id) > 0)
    )
    
    if last_name:
        # Case-insensitive search on both last_name and maiden_name
        search_term = last_name.lower()
        query = query.filter(
            (func.lower(Person.last_name).contains(search_term)) |
            ((Person.maiden_name.isnot(None)) & (func.lower(Person.maiden_name).contains(search_term)))
        )
    
    results = query.order_by(Person.last_name.asc(), Person.first_name.asc()).all()
    
    items = [
        PersonWithFacesResponse(
            id=person.id,
            first_name=person.first_name,
            last_name=person.last_name,
            middle_name=person.middle_name,
            maiden_name=person.maiden_name,
            date_of_birth=person.date_of_birth,
            face_count=face_count,
        )
        for person, face_count in results
    ]
    
    return PeopleWithFacesListResponse(items=items, total=len(items))


@router.post("", response_model=PersonResponse, status_code=status.HTTP_201_CREATED)
def create_person(request: PersonCreateRequest, db: Session = Depends(get_db)) -> PersonResponse:
    """Create a new person."""
    person = Person(
        first_name=request.first_name,
        last_name=request.last_name,
        middle_name=request.middle_name,
        maiden_name=request.maiden_name,
        date_of_birth=request.date_of_birth,
    )
    db.add(person)
    try:
        db.commit()
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    db.refresh(person)
    return PersonResponse.model_validate(person)


@router.get("/{person_id}", response_model=PersonResponse)
def get_person(person_id: int, db: Session = Depends(get_db)) -> PersonResponse:
    """Get person by ID."""
    person = db.query(Person).filter(Person.id == person_id).first()
    if not person:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Person {person_id} not found")
    return PersonResponse.model_validate(person)


@router.put("/{person_id}", response_model=PersonResponse)
def update_person(
    person_id: int,
    request: PersonUpdateRequest,
    db: Session = Depends(get_db),
) -> PersonResponse:
    """Update person information."""
    person = db.query(Person).filter(Person.id == person_id).first()
    if not person:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Person {person_id} not found")
    
    # Update fields
    person.first_name = request.first_name.strip()
    person.last_name = request.last_name.strip()
    person.middle_name = request.middle_name.strip() if request.middle_name else None
    person.maiden_name = request.maiden_name.strip() if request.maiden_name else None
    person.date_of_birth = request.date_of_birth
    
    try:
        db.commit()
        db.refresh(person)
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    
    return PersonResponse.model_validate(person)


@router.get("/{person_id}/faces", response_model=PersonFacesResponse)
def get_person_faces(person_id: int, db: Session = Depends(get_db)) -> PersonFacesResponse:
    """Get all faces for a specific person."""
    person = db.query(Person).filter(Person.id == person_id).first()
    if not person:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Person {person_id} not found")
    
    from src.web.db.models import Photo
    
    faces = (
        db.query(Face)
        .join(Photo, Face.photo_id == Photo.id)
        .filter(Face.person_id == person_id)
        .order_by(Photo.filename)
        .all()
    )
    
    items = [
        PersonFaceItem(
            id=face.id,
            photo_id=face.photo_id,
            photo_path=face.photo.path,
            photo_filename=face.photo.filename,
            location=face.location,
            face_confidence=float(face.face_confidence),
            quality_score=float(face.quality_score),
            detector_backend=face.detector_backend,
            model_name=face.model_name,
        )
        for face in faces
    ]
    
    return PersonFacesResponse(person_id=person_id, items=items, total=len(items))


@router.post("/{person_id}/accept-matches", response_model=IdentifyFaceResponse)
def accept_matches(
    person_id: int,
    request: AcceptMatchesRequest,
    db: Session = Depends(get_db),
) -> IdentifyFaceResponse:
    """Accept auto-match matches for a person.
    
    Matches desktop auto-match save workflow exactly:
    1. Identifies selected faces with this person
    2. Inserts person_encodings for each identified face
    3. Updates person encodings (removes old, adds current)
    """
    identified_count, updated_count = accept_auto_match_matches(
        db, person_id, request.face_ids
    )
    
    return IdentifyFaceResponse(
        identified_face_ids=request.face_ids,
        person_id=person_id,
        created_person=False,
    )

