from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from datetime import datetime, date
from typing import Optional
import uuid

from backend.database import get_db
from backend.models import DeploymentRecord, RosterUnit

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


def _serialize(record: DeploymentRecord) -> dict:
    return {
        "id": record.id,
        "unit_id": record.unit_id,
        "deployed_date": record.deployed_date.isoformat() if record.deployed_date else None,
        "estimated_removal_date": record.estimated_removal_date.isoformat() if record.estimated_removal_date else None,
        "actual_removal_date": record.actual_removal_date.isoformat() if record.actual_removal_date else None,
        "project_ref": record.project_ref,
        "project_id": record.project_id,
        "location_name": record.location_name,
        "notes": record.notes,
        "created_at": record.created_at.isoformat() if record.created_at else None,
        "updated_at": record.updated_at.isoformat() if record.updated_at else None,
        "is_active": record.actual_removal_date is None,
    }


@router.get("/deployments/{unit_id}")
def get_deployments(unit_id: str, db: Session = Depends(get_db)):
    """Get all deployment records for a unit, newest first."""
    unit = db.query(RosterUnit).filter_by(id=unit_id).first()
    if not unit:
        raise HTTPException(status_code=404, detail=f"Unit {unit_id} not found")

    records = (
        db.query(DeploymentRecord)
        .filter_by(unit_id=unit_id)
        .order_by(DeploymentRecord.deployed_date.desc(), DeploymentRecord.created_at.desc())
        .all()
    )
    return {"deployments": [_serialize(r) for r in records]}


@router.get("/deployments/{unit_id}/active")
def get_active_deployment(unit_id: str, db: Session = Depends(get_db)):
    """Get the current active deployment (actual_removal_date is NULL), or null."""
    record = (
        db.query(DeploymentRecord)
        .filter(
            DeploymentRecord.unit_id == unit_id,
            DeploymentRecord.actual_removal_date == None
        )
        .order_by(DeploymentRecord.created_at.desc())
        .first()
    )
    return {"deployment": _serialize(record) if record else None}


@router.post("/deployments/{unit_id}")
def create_deployment(unit_id: str, payload: dict, db: Session = Depends(get_db)):
    """
    Create a new deployment record for a unit.

    Body fields (all optional):
        deployed_date         (YYYY-MM-DD)
        estimated_removal_date (YYYY-MM-DD)
        project_ref           (freeform string)
        project_id            (UUID if linked to Project)
        location_name
        notes
    """
    unit = db.query(RosterUnit).filter_by(id=unit_id).first()
    if not unit:
        raise HTTPException(status_code=404, detail=f"Unit {unit_id} not found")

    def parse_date(val) -> Optional[date]:
        if not val:
            return None
        if isinstance(val, date):
            return val
        return date.fromisoformat(str(val))

    record = DeploymentRecord(
        id=str(uuid.uuid4()),
        unit_id=unit_id,
        deployed_date=parse_date(payload.get("deployed_date")),
        estimated_removal_date=parse_date(payload.get("estimated_removal_date")),
        actual_removal_date=None,
        project_ref=payload.get("project_ref"),
        project_id=payload.get("project_id"),
        location_name=payload.get("location_name"),
        notes=payload.get("notes"),
        created_at=datetime.utcnow(),
        updated_at=datetime.utcnow(),
    )
    db.add(record)
    db.commit()
    db.refresh(record)
    return _serialize(record)


@router.put("/deployments/{unit_id}/{deployment_id}")
def update_deployment(unit_id: str, deployment_id: str, payload: dict, db: Session = Depends(get_db)):
    """
    Update a deployment record. Used for:
    - Setting/changing estimated_removal_date
    - Closing a deployment (set actual_removal_date to mark unit returned)
    - Editing project_ref, location_name, notes
    """
    record = db.query(DeploymentRecord).filter_by(id=deployment_id, unit_id=unit_id).first()
    if not record:
        raise HTTPException(status_code=404, detail="Deployment record not found")

    def parse_date(val) -> Optional[date]:
        if val is None:
            return None
        if val == "":
            return None
        if isinstance(val, date):
            return val
        return date.fromisoformat(str(val))

    if "deployed_date" in payload:
        record.deployed_date = parse_date(payload["deployed_date"])
    if "estimated_removal_date" in payload:
        record.estimated_removal_date = parse_date(payload["estimated_removal_date"])
    if "actual_removal_date" in payload:
        record.actual_removal_date = parse_date(payload["actual_removal_date"])
    if "project_ref" in payload:
        record.project_ref = payload["project_ref"]
    if "project_id" in payload:
        record.project_id = payload["project_id"]
    if "location_name" in payload:
        record.location_name = payload["location_name"]
    if "notes" in payload:
        record.notes = payload["notes"]

    record.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(record)
    return _serialize(record)


@router.delete("/deployments/{unit_id}/{deployment_id}")
def delete_deployment(unit_id: str, deployment_id: str, db: Session = Depends(get_db)):
    """Delete a deployment record."""
    record = db.query(DeploymentRecord).filter_by(id=deployment_id, unit_id=unit_id).first()
    if not record:
        raise HTTPException(status_code=404, detail="Deployment record not found")
    db.delete(record)
    db.commit()
    return {"ok": True}
