from fastapi import APIRouter, Depends, Query, status, HTTPException, Body
from sqlalchemy.orm import Session
from typing import Optional
from datetime import date
from utils.utils import get_db
from . import handler
from .schema import (
    LoancalculationCreate,
    LoancalculationUpdate,
    LoancalculationResponse,
    LoancalculationDetailResponse,
    PaginatedLoancalculationResponse,
    AmortizationscheduleentryResponse,
    PaginatedAmortizationscheduleentryResponse,
)

router = APIRouter(prefix="/loan-calculations", tags=["Loan Calculations"])


@router.post(
    "/",
    response_model=LoancalculationResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Loan Calculation",
    description="Creates a new loan calculation record with computed monthly payment, total payment, and total interest based on principal, annual interest rate, and loan term. Validates inputs against system constraints and stores the calculation with a session identifier for tracking.",
)
def create_loan_calculation_route(data: LoancalculationCreate, db: Session = Depends(get_db)):
    return handler.create_loan_calculation(db, data)


@router.get(
    "/{calculation_id}",
    response_model=LoancalculationResponse,
    summary="Get Loan Calculation",
    description="Retrieves a stored loan calculation by ID. Returns 404 if the calculation does not exist.",
)
def get_loan_calculation_route(calculation_id: str, db: Session = Depends(get_db)):
    return handler.get_loan_calculation(db, calculation_id)


@router.get(
    "/",
    response_model=PaginatedLoancalculationResponse,
    summary="List Loan Calculations",
    description="Returns a paginated list of loan calculations. Supports optional filtering by session_id to retrieve calculations for a specific user session.",
)
def list_loan_calculations_route(
    limit: int = Query(20, ge=1),
    offset: int = Query(0, ge=0),
    session_id: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    return handler.list_loan_calculations(db, limit, offset, session_id=session_id)


@router.put(
    "/{calculation_id}",
    response_model=LoancalculationResponse,
    summary="Update Loan Calculation",
    description="Updates an existing loan calculation. All fields are optional; only provided fields will be updated. Returns 404 if the calculation does not exist.",
)
def update_loan_calculation_route(
    calculation_id: str,
    data: LoancalculationUpdate,
    db: Session = Depends(get_db),
):
    return handler.update_loan_calculation(db, calculation_id, data)


@router.delete(
    "/{calculation_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete Loan Calculation",
    description="Deletes a loan calculation and all associated amortization schedule entries. Returns 404 if the calculation does not exist.",
)
def delete_loan_calculation_route(calculation_id: str, db: Session = Depends(get_db)):
    handler.delete_loan_calculation(db, calculation_id)


@router.get(
    "/{calculation_id}/details",
    response_model=LoancalculationDetailResponse,
    summary="Get Loan Calculation with Details",
    description="Retrieves a loan calculation along with its complete amortization schedule showing payment breakdown for each period. Returns 404 if the calculation does not exist.",
)
def get_loan_calculation_details_route(calculation_id: str, db: Session = Depends(get_db)):
    return handler.get_loan_calculation_with_details(db, calculation_id)


@router.post(
    "/{calculation_id}/generate-schedule",
    response_model=LoancalculationDetailResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Generate Amortization Schedule",
    description="Generates a complete amortization schedule for an existing loan calculation by iterating through each payment period and creating schedule entries. Deletes any existing schedule entries for this calculation before generating new ones. Optional start_date parameter allows specifying the first payment date; defaults to today.",
)
def generate_amortization_schedule_route(
    calculation_id: str,
    start_date: Optional[date] = Body(None, embed=True),
    db: Session = Depends(get_db),
):
    return handler.generate_amortization_schedule(db, calculation_id, start_date=start_date)


@router.get(
    "/{calculation_id}/schedule-entries",
    response_model=PaginatedAmortizationscheduleentryResponse,
    summary="List Amortization Schedule Entries",
    description="Returns a paginated list of amortization schedule entries for a specific loan calculation, ordered by payment number.",
)
def list_schedule_entries_route(
    calculation_id: str,
    limit: int = Query(20, ge=1),
    offset: int = Query(0, ge=0),
    db: Session = Depends(get_db),
):
    return handler.list_amortization_schedule_entries(db, limit, offset, calculation_id=calculation_id)