from typing import List, Optional
from fastapi import APIRouter, Depends, status
from sqlalchemy.orm import Session, joinedload
from app.core.database import get_db
from app.models.employee import Employee
from app.models.salary_history import SalaryHistory
from app.models.payroll_run import PayrollRunItem, PayrollRun
from app.schemas.salary import (
    SalaryHistoryCreate,
    SalaryHistoryOut,
    SalaryRecommendation,
    BulkIncreaseRequest,
)
from app.schemas.payroll import PayrollPaymentHistoryOut
from app.helpers.crud import get_or_404
from datetime import datetime, timezone

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


# ── Per-employee salary history ────────────────────────────────────────────────

@router.get(
    "/employees/{employee_id}/salary-history",
    response_model=List[SalaryHistoryOut],
)
def get_salary_history(employee_id: str, db: Session = Depends(get_db)):
    get_or_404(db, Employee, employee_id, "Employee")
    return (
        db.query(SalaryHistory)
        .filter(SalaryHistory.employee_id == employee_id)
        .order_by(SalaryHistory.effective_date)
        .all()
    )


@router.post(
    "/employees/{employee_id}/salary-history",
    response_model=SalaryHistoryOut,
    status_code=status.HTTP_201_CREATED,
)
def add_salary_history(
    employee_id: str,
    body: SalaryHistoryCreate,
    db: Session = Depends(get_db),
):
    emp = get_or_404(db, Employee, employee_id, "Employee")
    record = SalaryHistory(
        employee_id=employee_id,
        old_salary=body.old_salary if body.old_salary is not None else emp.base_salary,
        new_salary=body.new_salary,
        effective_date=body.effective_date,
        notes=body.notes,
    )
    emp.base_salary = body.new_salary
    emp.updated_at = datetime.now(timezone.utc)
    db.add(record)
    db.commit()
    db.refresh(record)
    return record


# ── Salary recommendations ─────────────────────────────────────────────────────

def _calc_recommendation(emp: Employee) -> SalaryRecommendation:
    history = sorted(emp.salary_history, key=lambda h: h.effective_date)
    loan_deduction = sum(
        l.monthly_deduction for l in emp.loans if l.status == "active"
    )
    net = emp.base_salary - loan_deduction
    last_date = history[-1].effective_date if history else None

    if len(history) < 2:
        pct = 5.0
        rec_increase = int(net * 0.05)
    else:
        increases_pct = []
        for i in range(1, len(history)):
            prev = history[i - 1].new_salary
            curr = history[i].new_salary
            if prev > 0:
                increases_pct.append((curr - prev) / prev * 100)

        if not increases_pct:
            pct = 5.0
        elif len(increases_pct) >= 3:
            recent = increases_pct[-2:]
            older = increases_pct[:-2]
            w_sum = sum(older) * 1 + sum(recent) * 2
            w_cnt = len(older) * 1 + len(recent) * 2
            pct = w_sum / w_cnt
        else:
            pct = sum(increases_pct) / len(increases_pct)

        rec_increase = int(net * (pct / 100))

    recent_history = sorted(emp.salary_history, key=lambda h: h.effective_date, reverse=True)[:2]

    return SalaryRecommendation(
        employee_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,
        last_salary_date=last_date,
        current_salary=emp.base_salary,
        loan_deduction=loan_deduction,
        net_salary=net,
        recommended_increase=rec_increase,
        recommended_new_net=net + rec_increase,
        recommended_pct=round(pct, 2),
        method="weighted_avg_pct" if len(history) >= 2 else "default_5pct",
        history_count=len(history),
        recent_history=recent_history,
    )


@router.get("/salary/recommendations", response_model=List[SalaryRecommendation])
def get_recommendations(
    active_only: bool = True,
    db: Session = Depends(get_db),
):
    query = db.query(Employee).options(
        joinedload(Employee.salary_history),
        joinedload(Employee.loans),
        joinedload(Employee.company_rel),
    )
    if active_only:
        query = query.filter(Employee.active == True)  # noqa: E712
    employees = query.order_by(Employee.name).all()
    return [_calc_recommendation(e) for e in employees]


# ── Bulk salary increase ────────────────────────────────────────────────────────

@router.post("/salary/bulk-increase", response_model=List[SalaryHistoryOut])
def bulk_increase(body: BulkIncreaseRequest, db: Session = Depends(get_db)):
    records = []
    for item in body.items:
        emp = get_or_404(db, Employee, item.employee_id, "Employee")
        record = SalaryHistory(
            employee_id=item.employee_id,
            old_salary=emp.base_salary,
            new_salary=item.new_base_salary,
            effective_date=item.effective_date,
            notes=item.notes,
        )
        emp.base_salary = item.new_base_salary
        emp.updated_at = datetime.now(timezone.utc)
        db.add(record)
        records.append(record)
    db.commit()
    for r in records:
        db.refresh(r)
    return records


# ── Employee payment history (from payroll runs) ───────────────────────────────

@router.get(
    "/employees/{employee_id}/payment-history",
    response_model=List[PayrollPaymentHistoryOut],
)
def get_employee_payment_history(employee_id: str, db: Session = Depends(get_db)):
    """Return all payroll export payments for a specific employee, newest first.
    Includes month, year, export_type and run_date from the parent PayrollRun."""
    get_or_404(db, Employee, employee_id, "Employee")
    items = (
        db.query(PayrollRunItem)
        .join(PayrollRun)
        .options(joinedload(PayrollRunItem.run))
        .filter(PayrollRunItem.employee_id == employee_id)
        .order_by(PayrollRun.year.desc(), PayrollRun.month.desc(), PayrollRun.run_date.desc())
        .all()
    )
    return [
        {
            "id": item.id,
            "run_id": item.run_id,
            "employee_id": item.employee_id,
            "employee_name": item.employee_name,
            "base_salary": item.base_salary,
            "benefit": item.benefit,
            "loan_deduction": item.loan_deduction,
            "cash_advance": item.cash_advance,
            "net_amount": item.net_amount,
            "has_override": item.has_override,
            "created_at": item.created_at,
            "month": item.run.month,
            "year": item.run.year,
            "export_type": item.run.export_type,
            "run_date": item.run.run_date,
        }
        for item in items
    ]
