from datetime import date, datetime
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, Query, status
from pydantic import BaseModel, ConfigDict
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.models import Employee
from app.core.security import get_current_user

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


class EmployeeBase(BaseModel):
    full_name: str
    preferred_name: str | None = None
    email: str | None = None
    phone: str | None = None
    role_title: str | None = None
    department: str | None = None
    employment_type: str | None = None
    ird_number: str | None = None
    start_date: date
    end_date: date | None = None
    status: str = "active"
    tax_notes: str | None = None
    notes: str | None = None


class EmployeeCreate(EmployeeBase):
    pass


class EmployeeUpdate(BaseModel):
    full_name: str | None = None
    preferred_name: str | None = None
    email: str | None = None
    phone: str | None = None
    role_title: str | None = None
    department: str | None = None
    employment_type: str | None = None
    ird_number: str | None = None
    start_date: date | None = None
    end_date: date | None = None
    status: str | None = None
    tax_notes: str | None = None
    notes: str | None = None


class EmployeeResponse(EmployeeBase):
    id: int
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)


class PaginatedEmployees(BaseModel):
    items: list[EmployeeResponse]
    total: int
    page: int
    page_size: int


def _employee_or_404(db: Session, employee_id: int) -> Employee:
    employee = db.get(Employee, employee_id)
    if not employee:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Employee not found")
    return employee


@router.get("", response_model=PaginatedEmployees)
def list_employees(
    current_user: Annotated[dict, Depends(get_current_user)],
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    status_filter: str = Query("", alias="status"),
    db: Session = Depends(get_db),
):
    query = db.query(Employee)
    if status_filter:
        query = query.filter(Employee.status == status_filter)

    total = query.count()
    items = (
        query.order_by(Employee.start_date.desc(), Employee.id.desc())
        .offset((page - 1) * page_size)
        .limit(page_size)
        .all()
    )
    return PaginatedEmployees(
        items=[EmployeeResponse.model_validate(item) for item in items],
        total=total,
        page=page,
        page_size=page_size,
    )


@router.post("", response_model=EmployeeResponse, status_code=status.HTTP_201_CREATED)
def create_employee(
    data: EmployeeCreate,
    current_user: Annotated[dict, Depends(get_current_user)],
    db: Session = Depends(get_db),
):
    employee = Employee(**data.model_dump())
    db.add(employee)
    db.commit()
    db.refresh(employee)
    return EmployeeResponse.model_validate(employee)


@router.get("/{employee_id}", response_model=EmployeeResponse)
def get_employee(
    employee_id: int,
    current_user: Annotated[dict, Depends(get_current_user)],
    db: Session = Depends(get_db),
):
    return EmployeeResponse.model_validate(_employee_or_404(db, employee_id))


@router.put("/{employee_id}", response_model=EmployeeResponse)
def update_employee(
    employee_id: int,
    data: EmployeeUpdate,
    current_user: Annotated[dict, Depends(get_current_user)],
    db: Session = Depends(get_db),
):
    employee = _employee_or_404(db, employee_id)
    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(employee, field, value)
    db.commit()
    db.refresh(employee)
    return EmployeeResponse.model_validate(employee)
