"""Finance endpoints for student ledger, payments, and device loans."""

from typing import Optional
from uuid import UUID

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

from app.api.deps import get_current_admin, get_current_user, get_db, require_user_type
from app.models.finance import (
    DeviceLoan, DeviceLoanPayment, DeviceLoanStatus, LedgerEntryStatus,
    LedgerEntryType, StudentLedger
)
from app.models.user import UserType
from app.schemas.common import SuccessResponse
from app.schemas.finance import (
    DeviceLoanCreate, DeviceLoanPaymentCreate, DeviceLoanPaymentResponse,
    DeviceLoanResponse, PaymentInitializeRequest, PaymentInitializeResponse,
    StudentLedgerCreate, StudentLedgerResponse
)

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


# ========== Student Ledger ==========
@router.get("/students/{student_id}/ledger", response_model=SuccessResponse)
async def get_student_ledger(
    student_id: UUID,
    academic_session_id: Optional[UUID] = Query(None),
    entry_type: Optional[LedgerEntryType] = Query(None),
    status: Optional[LedgerEntryStatus] = Query(None),
    db: Session = Depends(get_db),
    current_user_data: dict = Depends(get_current_user),
):
    """Get student financial ledger."""
    # Students can only see their own ledger
    user_data = current_user_data
    if user_data.get("type") == "user":
        user = user_data.get("user")
        if user.user_type == UserType.GLOBAL_UNDERGRADUATE and str(user.id) != str(student_id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only view your own ledger",
            )
    
    query = db.query(StudentLedger).filter(StudentLedger.student_id == student_id)
    
    if academic_session_id:
        query = query.filter(StudentLedger.academic_session_id == academic_session_id)
    if entry_type:
        query = query.filter(StudentLedger.entry_type == entry_type)
    if status:
        query = query.filter(StudentLedger.status == status)
    
    entries = query.order_by(StudentLedger.created_at.desc()).all()
    
    # Calculate totals
    total_due = sum(float(e.amount) for e in entries if e.status == LedgerEntryStatus.PENDING)
    total_paid = sum(float(e.amount) for e in entries if e.status == LedgerEntryStatus.PAID)
    balance = total_due - total_paid
    
    return SuccessResponse(
        data={
            "entries": [StudentLedgerResponse.model_validate(e).model_dump() for e in entries],
            "summary": {
                "total_due": total_due,
                "total_paid": total_paid,
                "balance": balance,
            },
        },
        message="Student ledger retrieved successfully",
    )


@router.post("/students/{student_id}/ledger", response_model=SuccessResponse, status_code=status.HTTP_201_CREATED)
async def create_ledger_entry(
    student_id: UUID,
    entry_data: StudentLedgerCreate,
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Create a ledger entry (bursar/admin only)."""
    # Verify student exists
    from app.models.user import User
    student = db.query(User).filter(User.id == student_id).first()
    if not student:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Student not found")
    
    # Ensure student_id matches
    entry_data.student_id = student_id
    
    entry = StudentLedger(**entry_data.model_dump())
    db.add(entry)
    db.commit()
    db.refresh(entry)
    
    return SuccessResponse(
        data=StudentLedgerResponse.model_validate(entry).model_dump(),
        message="Ledger entry created successfully",
    )


# ========== Payment Initialization ==========
@router.post("/payments/initialize", response_model=SuccessResponse)
async def initialize_payment(
    payment_data: PaymentInitializeRequest,
    db: Session = Depends(get_db),
    current_user_data: dict = Depends(get_current_user),
):
    """Initialize a payment (returns payment link/secret for frontend)."""
    # Verify student
    user_data = current_user_data
    if user_data.get("type") == "user":
        user = user_data.get("user")
        if user.user_type != UserType.GLOBAL_UNDERGRADUATE or str(user.id) != str(payment_data.student_id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only initialize payments for yourself",
            )
    
    # TODO: Integrate with payment gateway (Paystack/Flutterwave)
    # For now, return a mock response
    from datetime import datetime, timedelta
    from uuid import uuid4
    
    payment_reference = f"PAY-{uuid4().hex[:12].upper()}"
    
    # In production, this would call Paystack/Flutterwave API
    # For now, return a mock payment URL
    payment_url = f"https://checkout.paystack.com/{payment_reference}"
    
    response_data = PaymentInitializeResponse(
        payment_reference=payment_reference,
        payment_url=payment_url,
        gateway="paystack",
        expires_at=datetime.utcnow() + timedelta(hours=24),
    )
    
    return SuccessResponse(
        data=response_data.model_dump(),
        message="Payment initialized successfully",
    )


# ========== Payment Webhook ==========
@router.post("/payments/webhook")
async def payment_webhook(
    request_data: dict,
    db: Session = Depends(get_db),
):
    """Handle payment gateway webhook (Paystack/Flutterwave)."""
    # TODO: Implement webhook verification and processing
    # This should:
    # 1. Verify webhook signature
    # 2. Update ledger entry status
    # 3. Update device loan payments if applicable
    # 4. Send confirmation email
    
    return {"status": "ok", "message": "Webhook received"}


# ========== Device Loans ==========
@router.get("/device-loans", response_model=SuccessResponse)
async def list_device_loans(
    student_id: Optional[UUID] = Query(None),
    status: Optional[DeviceLoanStatus] = Query(None),
    db: Session = Depends(get_db),
    current_user_data: dict = Depends(get_current_user),
):
    """List device loans."""
    query = db.query(DeviceLoan)
    
    # Students can only see their own loans
    user_data = current_user_data
    if user_data.get("type") == "user":
        user = user_data.get("user")
        if user.user_type == UserType.GLOBAL_UNDERGRADUATE:
            query = query.filter(DeviceLoan.student_id == user.id)
    
    if student_id:
        query = query.filter(DeviceLoan.student_id == student_id)
    if status:
        query = query.filter(DeviceLoan.status == status)
    
    loans = query.order_by(DeviceLoan.created_at.desc()).all()
    
    return SuccessResponse(
        data=[DeviceLoanResponse.model_validate(l).model_dump() for l in loans],
        message="Device loans retrieved successfully",
    )


@router.post("/device-loans", response_model=SuccessResponse, status_code=status.HTTP_201_CREATED)
async def create_device_loan(
    loan_data: DeviceLoanCreate,
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Create a device loan (bursar/admin only)."""
    # Verify student exists
    from app.models.user import User
    student = db.query(User).filter(User.id == loan_data.student_id).first()
    if not student:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Student not found")
    
    loan = DeviceLoan(**loan_data.model_dump())
    db.add(loan)
    db.commit()
    db.refresh(loan)
    
    return SuccessResponse(
        data=DeviceLoanResponse.model_validate(loan).model_dump(),
        message="Device loan created successfully",
    )


@router.get("/device-loans/stats", response_model=SuccessResponse)
async def get_device_loan_stats(
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Get device loan statistics for bursar dashboard."""
    total_loans = db.query(DeviceLoan).count()
    active_loans = db.query(DeviceLoan).filter(DeviceLoan.status == DeviceLoanStatus.ACTIVE).count()
    completed_loans = db.query(DeviceLoan).filter(DeviceLoan.status == DeviceLoanStatus.COMPLETED).count()
    defaulted_loans = db.query(DeviceLoan).filter(DeviceLoan.status == DeviceLoanStatus.DEFAULTED).count()
    
    # Calculate total loan amount
    from sqlalchemy import func
    total_amount = db.query(func.sum(DeviceLoan.loan_amount)).scalar() or 0
    
    return SuccessResponse(
        data={
            "total_loans": total_loans,
            "active_loans": active_loans,
            "completed_loans": completed_loans,
            "defaulted_loans": defaulted_loans,
            "total_amount": float(total_amount),
        },
        message="Device loan statistics retrieved successfully",
    )


@router.get("/stats", response_model=SuccessResponse)
async def get_finance_stats(
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Get comprehensive finance statistics for bursar dashboard."""
    from sqlalchemy import func
    
    # Ledger statistics
    total_ledger_entries = db.query(StudentLedger).count()
    pending_entries = (
        db.query(StudentLedger)
        .filter(StudentLedger.status == LedgerEntryStatus.PENDING)
        .count()
    )
    paid_entries = (
        db.query(StudentLedger)
        .filter(StudentLedger.status == LedgerEntryStatus.PAID)
        .count()
    )
    overdue_entries = (
        db.query(StudentLedger)
        .filter(StudentLedger.status == LedgerEntryStatus.OVERDUE)
        .count()
    )
    
    # Financial totals
    total_pending = (
        db.query(func.sum(StudentLedger.amount))
        .filter(StudentLedger.status == LedgerEntryStatus.PENDING)
        .scalar() or 0
    )
    total_paid = (
        db.query(func.sum(StudentLedger.amount))
        .filter(StudentLedger.status == LedgerEntryStatus.PAID)
        .scalar() or 0
    )
    total_overdue = (
        db.query(func.sum(StudentLedger.amount))
        .filter(StudentLedger.status == LedgerEntryStatus.OVERDUE)
        .scalar() or 0
    )
    
    # Device loans
    total_loans = db.query(DeviceLoan).count()
    active_loans = (
        db.query(DeviceLoan)
        .filter(DeviceLoan.status == DeviceLoanStatus.ACTIVE)
        .count()
    )
    completed_loans = (
        db.query(DeviceLoan)
        .filter(DeviceLoan.status == DeviceLoanStatus.COMPLETED)
        .count()
    )
    defaulted_loans = (
        db.query(DeviceLoan)
        .filter(DeviceLoan.status == DeviceLoanStatus.DEFAULTED)
        .count()
    )
    
    total_loan_amount = (
        db.query(func.sum(DeviceLoan.loan_amount))
        .scalar() or 0
    )
    
    return SuccessResponse(
        data={
            "ledger": {
                "total_entries": total_ledger_entries,
                "pending": pending_entries,
                "paid": paid_entries,
                "overdue": overdue_entries,
                "total_pending_amount": float(total_pending),
                "total_paid_amount": float(total_paid),
                "total_overdue_amount": float(total_overdue),
            },
            "device_loans": {
                "total": total_loans,
                "active": active_loans,
                "completed": completed_loans,
                "defaulted": defaulted_loans,
                "total_amount": float(total_loan_amount),
            },
        },
        message="Finance statistics retrieved successfully",
    )


@router.put("/device-loans/{loan_id}", response_model=SuccessResponse)
async def update_device_loan(
    loan_id: UUID,
    loan_data: dict,
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Update device loan status (bursar/admin only)."""
    loan = db.query(DeviceLoan).filter(DeviceLoan.id == loan_id).first()
    if not loan:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Device loan not found")
    
    # Update allowed fields
    if "status" in loan_data:
        loan.status = loan_data["status"]
    if "months_paid" in loan_data:
        loan.months_paid = loan_data["months_paid"]
    if "completion_date" in loan_data:
        loan.completion_date = loan_data["completion_date"]
    if "notes" in loan_data:
        loan.notes = loan_data["notes"]
    
    db.commit()
    db.refresh(loan)
    
    return SuccessResponse(
        data=DeviceLoanResponse.model_validate(loan).model_dump(),
        message="Device loan updated successfully",
    )
