"""General Ledger & Trial Balance API — Phase 5.3."""
from __future__ import annotations

from decimal import Decimal
from uuid import UUID

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, require_tenant
from app.core.security import get_current_user
from app.repositories.ledger import LedgerBalanceRepository
from app.services.balance_engine import BalanceEngine
from shared.security import CurrentUser

router = APIRouter()


class BalanceRead(BaseModel):
    account_id: UUID
    fiscal_period_id: UUID
    opening_balance: Decimal
    debit_total: Decimal
    credit_total: Decimal
    closing_balance: Decimal
    current_balance: Decimal

    model_config = {"from_attributes": True}


class TrialBalanceRead(BaseModel):
    fiscal_period_id: UUID
    total_debit: Decimal
    total_credit: Decimal
    difference: Decimal
    is_balanced: bool


@router.get("/balances/{account_id}", response_model=BalanceRead | None)
async def get_account_balance(
    account_id: UUID,
    fiscal_period_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    repo = LedgerBalanceRepository(db)
    balance = await repo.get_by_account_period(tenant_id, account_id, fiscal_period_id)
    return balance


@router.get("/balances", response_model=list[BalanceRead])
async def list_period_balances(
    fiscal_period_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    repo = LedgerBalanceRepository(db)
    return await repo.list_by_period(tenant_id, fiscal_period_id)


@router.post("/trial-balance", response_model=TrialBalanceRead)
async def generate_trial_balance(
    fiscal_period_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    engine = BalanceEngine(db)
    snapshot = await engine.generate_trial_balance(tenant_id, fiscal_period_id)
    await db.commit()
    return TrialBalanceRead(
        fiscal_period_id=snapshot.fiscal_period_id,
        total_debit=snapshot.total_debit,
        total_credit=snapshot.total_credit,
        difference=snapshot.difference,
        is_balanced=snapshot.is_balanced,
    )


@router.post("/recalculate")
async def recalculate_balances(
    fiscal_period_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    engine = BalanceEngine(db)
    count = await engine.recalculate_period(tenant_id, fiscal_period_id)
    await db.commit()
    return {"recalculated_accounts": count}
