from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime
from pydantic import BaseModel
from app.database import get_db
from app.models.area_unavailability import AsimAreaUnavailability
from app.models.area import Area
from app.core.security import require_pengurus

router = APIRouter(prefix="/api/area-unavailabilities", tags=["Area Unavailabilities"])


class AreaUnavailCreate(BaseModel):
    asim_id: int
    area_ids: List[int]
    reason: Optional[str] = None
    status: Optional[str] = 'pending'


class AreaUnavailResponse(BaseModel):
    id: int
    asim_id: int
    asim_name: Optional[str] = None
    asim_no: Optional[int] = None
    area_id: int
    area_nama: Optional[str] = None
    reason: Optional[str] = None
    status: str
    is_active: bool
    created_at: Optional[datetime] = None

    class Config:
        from_attributes = True


def _to_response(au: AsimAreaUnavailability) -> AreaUnavailResponse:
    return AreaUnavailResponse(
        id=au.id,
        asim_id=au.asim_id,
        asim_name=au.asim.full_name if au.asim else None,
        asim_no=au.asim.no_asim if au.asim else None,
        area_id=au.area_id,
        area_nama=au.area.nama if au.area else None,
        reason=au.reason,
        status=au.status,
        is_active=au.is_active,
        created_at=au.created_at,
    )


@router.get("/", response_model=List[AreaUnavailResponse])
def get_all(asim_id: Optional[int] = None, status: Optional[str] = None, db: Session = Depends(get_db)):
    q = db.query(AsimAreaUnavailability)
    if asim_id:
        q = q.filter(AsimAreaUnavailability.asim_id == asim_id)
    if status:
        q = q.filter(AsimAreaUnavailability.status == status)
    return [_to_response(au) for au in q.order_by(AsimAreaUnavailability.created_at.desc()).all()]


@router.post("/", response_model=List[AreaUnavailResponse])
def create(data: AreaUnavailCreate, db: Session = Depends(get_db)):
    if not data.area_ids:
        return []

    # Batch: validate all area_ids in one query
    valid_areas = {
        a.id for a in db.query(Area).filter(
            Area.id.in_(data.area_ids), Area.is_active == True
        ).all()
    }
    for area_id in data.area_ids:
        if area_id not in valid_areas:
            raise HTTPException(status_code=404, detail=f"Area {area_id} tidak ditemukan")

    # Batch: check existing pending entries in one query
    existing_map = {
        au.area_id: au for au in db.query(AsimAreaUnavailability).filter(
            AsimAreaUnavailability.asim_id == data.asim_id,
            AsimAreaUnavailability.area_id.in_(data.area_ids),
            AsimAreaUnavailability.status == 'pending',
        ).all()
    }

    results = []
    for area_id in data.area_ids:
        existing = existing_map.get(area_id)
        if existing:
            results.append(_to_response(existing))
            continue
        final_status = data.status or 'pending'
        au = AsimAreaUnavailability(
            asim_id=data.asim_id,
            area_id=area_id,
            reason=data.reason,
            status=final_status,
            is_active=(final_status == 'approved'),
        )
        db.add(au)
        db.flush()
        db.refresh(au)
        results.append(_to_response(au))
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan area unavailability")
    return results


@router.put("/{unavail_id}/approve", dependencies=[Depends(require_pengurus)])
def approve(unavail_id: int, db: Session = Depends(get_db)):
    au = db.query(AsimAreaUnavailability).filter(AsimAreaUnavailability.id == unavail_id).first()
    if not au:
        raise HTTPException(status_code=404, detail="Tidak ditemukan")
    au.status = 'approved'
    au.is_active = True
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyetujui area unavailability")
    return {"message": "Disetujui"}


@router.put("/{unavail_id}/reject", dependencies=[Depends(require_pengurus)])
def reject(unavail_id: int, db: Session = Depends(get_db)):
    au = db.query(AsimAreaUnavailability).filter(AsimAreaUnavailability.id == unavail_id).first()
    if not au:
        raise HTTPException(status_code=404, detail="Tidak ditemukan")
    au.status = 'rejected'
    au.is_active = False
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menolak area unavailability")
    return {"message": "Ditolak"}


@router.delete("/{unavail_id}/deactivate")
def deactivate(unavail_id: int, db: Session = Depends(get_db)):
    au = db.query(AsimAreaUnavailability).filter(AsimAreaUnavailability.id == unavail_id).first()
    if not au:
        raise HTTPException(status_code=404, detail="Tidak ditemukan")
    db.delete(au)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus area unavailability")
    return {"message": "Area unavailability dihapus"}
