from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session
from typing import Optional, List
from utils.utils import get_db
from . import handler
from .schema import (
    ExpenseCreate,
    ExpenseUpdate,
    ExpenseResponse,
    CommissionCreate,
    CommissionUpdate,
    CommissionResponse,
    ExpenseStatus,
    CommissionStatus,
)
from datetime import datetime

router = APIRouter(prefix="/financial", tags=["Financial Management"])


@router.post(
    "/expenses",
    response_model=ExpenseResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Expense",
    description="Creates a new expense record for a tour schedule or general operational cost. Validates that the submitter user exists and the tour schedule exists if provided. Returns 404 if referenced entities are not found.",
)
def create_expense_route(data: ExpenseCreate, db: Session = Depends(get_db)):
    return handler.create_expense(db, data)


@router.get(
    "/expenses/{expense_id}",
    response_model=ExpenseResponse,
    summary="Get Expense By ID",
    description="Retrieves a single expense record by its unique identifier. Returns 404 if the expense does not exist.",
)
def get_expense_route(expense_id: str, db: Session = Depends(get_db)):
    return handler.get_expense(db, expense_id)


@router.get(
    "/expenses",
    response_model=List[ExpenseResponse],
    summary="List Expenses",
    description="Returns a paginated list of expense records. Supports optional filters for status, tour schedule, and submitter. Results are ordered by creation date descending.",
)
def list_expenses_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    status_filter: Optional[ExpenseStatus] = Query(None),
    tour_schedule_id: Optional[str] = None,
    submitted_by: Optional[str] = None,
    db: Session = Depends(get_db),
):
    return handler.list_expenses(db, limit, offset, status_filter, tour_schedule_id, submitted_by)


@router.put(
    "/expenses/{expense_id}",
    response_model=ExpenseResponse,
    summary="Update Expense",
    description="Updates an existing expense record. Only provided fields are updated. Validates that referenced users and tour schedules exist. Returns 404 if the expense or referenced entities are not found.",
)
def update_expense_route(expense_id: str, data: ExpenseUpdate, db: Session = Depends(get_db)):
    return handler.update_expense(db, expense_id, data)


@router.delete(
    "/expenses/{expense_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Expense",
    description="Deletes an expense record by its unique identifier. Returns 404 if the expense does not exist.",
)
def delete_expense_route(expense_id: str, db: Session = Depends(get_db)):
    return handler.delete_expense(db, expense_id)


@router.post(
    "/expenses/{expense_id}/approve",
    response_model=ExpenseResponse,
    summary="Approve Expense",
    description="Approves a pending expense. Updates the status to approved, records the approver and approval date. Returns 400 if the expense is not in pending status, 404 if the expense or approver user does not exist.",
)
def approve_expense_route(expense_id: str, approved_by: str, db: Session = Depends(get_db)):
    return handler.approve_expense(db, expense_id, approved_by)


@router.post(
    "/expenses/{expense_id}/reject",
    response_model=ExpenseResponse,
    summary="Reject Expense",
    description="Rejects a pending expense. Updates the status to rejected, records the rejector and rejection date. Optional notes can be provided. Returns 400 if the expense is not in pending status, 404 if the expense or rejector user does not exist.",
)
def reject_expense_route(
    expense_id: str,
    rejected_by: str,
    notes: Optional[str] = None,
    db: Session = Depends(get_db),
):
    return handler.reject_expense(db, expense_id, rejected_by, notes)


@router.post(
    "/commissions",
    response_model=CommissionResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Commission",
    description="Creates a new commission record for a booking agent. Validates that the booking and agent user exist. Commission amount is calculated based on booking amount and commission rate. Returns 404 if referenced entities are not found.",
)
def create_commission_route(data: CommissionCreate, db: Session = Depends(get_db)):
    return handler.create_commission(db, data)


@router.get(
    "/commissions/{commission_id}",
    response_model=CommissionResponse,
    summary="Get Commission By ID",
    description="Retrieves a single commission record by its unique identifier. Returns 404 if the commission does not exist.",
)
def get_commission_route(commission_id: str, db: Session = Depends(get_db)):
    return handler.get_commission(db, commission_id)


@router.get(
    "/commissions",
    response_model=List[CommissionResponse],
    summary="List Commissions",
    description="Returns a paginated list of commission records. Supports optional filters for status and booking agent. Results are ordered by creation date descending.",
)
def list_commissions_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    status_filter: Optional[CommissionStatus] = Query(None),
    booking_agent_id: Optional[str] = None,
    db: Session = Depends(get_db),
):
    return handler.list_commissions(db, limit, offset, status_filter, booking_agent_id)


@router.put(
    "/commissions/{commission_id}",
    response_model=CommissionResponse,
    summary="Update Commission",
    description="Updates an existing commission record. Only provided fields are updated. Validates that referenced booking and agent user exist. Returns 404 if the commission or referenced entities are not found.",
)
def update_commission_route(commission_id: str, data: CommissionUpdate, db: Session = Depends(get_db)):
    return handler.update_commission(db, commission_id, data)


@router.delete(
    "/commissions/{commission_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Commission",
    description="Deletes a commission record by its unique identifier. Returns 404 if the commission does not exist.",
)
def delete_commission_route(commission_id: str, db: Session = Depends(get_db)):
    return handler.delete_commission(db, commission_id)


@router.post(
    "/commissions/{commission_id}/approve",
    response_model=CommissionResponse,
    summary="Approve Commission",
    description="Approves a pending commission. Updates the status to approved. Returns 400 if the commission is not in pending status, 404 if the commission does not exist.",
)
def approve_commission_route(commission_id: str, db: Session = Depends(get_db)):
    return handler.approve_commission(db, commission_id)


@router.post(
    "/commissions/{commission_id}/pay",
    response_model=CommissionResponse,
    summary="Pay Commission",
    description="Marks an approved commission as paid and records the payment date. Returns 400 if the commission is not in approved status (must be approved before payment), 404 if the commission does not exist.",
)
def pay_commission_route(commission_id: str, payment_date: datetime, db: Session = Depends(get_db)):
    return handler.pay_commission(db, commission_id, payment_date)