from typing import List, Optional
from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session, joinedload
from datetime import datetime, timezone
from app.core.database import get_db
from app.models.employee import Employee
from app.models.loan import Loan
from app.schemas.employee import (
    EmployeeCreate,
    EmployeeUpdate,
    EmployeeOut,
    EmployeeTableRow,
)
from app.helpers.crud import get_or_404

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


def _build_employee_out(emp: Employee) -> EmployeeOut:
    return EmployeeOut(
        id=emp.id,
        name=emp.name,
        account_name=emp.account_name,
        account_number=emp.account_number,
        company_id=emp.company_id,
        company_name=emp.company_rel.name if emp.company_rel else None,
        bank_name=emp.company_rel.bank_name if emp.company_rel else None,
        hire_date=emp.hire_date,
        base_salary=emp.base_salary,
        active=emp.active,
        created_at=emp.created_at,
        updated_at=emp.updated_at,
    )


@router.get("/table", response_model=List[EmployeeTableRow])
def employee_table(
    active_only: bool = Query(True),
    company_id: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    query = (
        db.query(Employee)
        .options(joinedload(Employee.company_rel), joinedload(Employee.loans))
    )
    if active_only:
        query = query.filter(Employee.active == True)  # noqa: E712
    if company_id:
        query = query.filter(Employee.company_id == company_id)

    employees = query.order_by(Employee.name).all()
    rows = []
    for emp in employees:
        loan_monthly = sum(
            l.monthly_deduction for l in emp.loans if l.status == "active"
        )
        net = emp.base_salary - loan_monthly
        rows.append(
            EmployeeTableRow(
                id=emp.id,
                name=emp.name,
                bank_name=emp.company_rel.bank_name if emp.company_rel else None,
                account_number=emp.account_number,
                account_name=emp.account_name,
                company_id=emp.company_id,
                company_name=emp.company_rel.name if emp.company_rel else None,
                hire_date=emp.hire_date,
                base_salary=emp.base_salary,
                benefit=0,
                loan_monthly=loan_monthly,
                current_salary=net,
                active=emp.active,
            )
        )
    return rows


@router.get("", response_model=List[EmployeeOut])
def list_employees(
    active_only: bool = Query(False),
    company_id: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    query = db.query(Employee).options(joinedload(Employee.company_rel))
    if active_only:
        query = query.filter(Employee.active == True)  # noqa: E712
    if company_id:
        query = query.filter(Employee.company_id == company_id)
    return [_build_employee_out(e) for e in query.order_by(Employee.name).all()]


@router.post("", response_model=EmployeeOut, status_code=status.HTTP_201_CREATED)
def create_employee(body: EmployeeCreate, db: Session = Depends(get_db)):
    employee = Employee(**body.model_dump())
    db.add(employee)
    db.commit()
    db.refresh(employee)
    # Reload with company
    db.expire(employee)
    emp = (
        db.query(Employee)
        .options(joinedload(Employee.company_rel))
        .filter(Employee.id == employee.id)
        .first()
    )
    return _build_employee_out(emp)


@router.get("/{employee_id}", response_model=EmployeeOut)
def get_employee(employee_id: str, db: Session = Depends(get_db)):
    emp = (
        db.query(Employee)
        .options(joinedload(Employee.company_rel))
        .filter(Employee.id == employee_id)
        .first()
    )
    if not emp:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Employee not found")
    return _build_employee_out(emp)


@router.put("/{employee_id}", response_model=EmployeeOut)
def update_employee(
    employee_id: str, body: EmployeeUpdate, db: Session = Depends(get_db)
):
    emp = get_or_404(db, Employee, employee_id, "Employee")
    for field, value in body.model_dump(exclude_none=True).items():
        setattr(emp, field, value)
    emp.updated_at = datetime.now(timezone.utc)
    db.commit()
    db.expire(emp)
    emp = (
        db.query(Employee)
        .options(joinedload(Employee.company_rel))
        .filter(Employee.id == employee_id)
        .first()
    )
    return _build_employee_out(emp)


@router.delete("/{employee_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_employee(employee_id: str, db: Session = Depends(get_db)):
    emp = get_or_404(db, Employee, employee_id, "Employee")
    db.delete(emp)
    db.commit()
