"""Phase 5 — Nursery production costing endpoints (finance-gated)."""
from __future__ import annotations
from datetime import date
from decimal import Decimal
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy.orm import Session
from app.database import get_db
from app.models.production import ProductionBatch
from app.services.auth import require_permission
from app.services import production_costing as pc

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


class BatchCostCreate(BaseModel):
    batch_id: str
    cost_type: str
    amount: Optional[float] = None
    quantity: Optional[float] = None
    unit: Optional[str] = None
    inventory_item_id: Optional[str] = None
    account_id: Optional[str] = None
    reference_type: Optional[str] = None
    reference_id: Optional[str] = None
    cost_center: Optional[str] = None
    notes: Optional[str] = None
    cost_date: Optional[date] = None


class ReadyCreate(BaseModel):
    ready_date: Optional[date] = None
    transfer_qty: Optional[int] = None


class MortalityCreate(BaseModel):
    quantity: int
    reason: Optional[str] = None
    cost_date: Optional[date] = None


def _fail(exc: Exception) -> HTTPException:
    return HTTPException(status_code=400, detail=str(exc))


@router.get("/production-costs")
def list_production_costs(
    batch_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(require_permission("accounting", "view")),
):
    return pc.list_batch_costs(db, batch_id=batch_id)


@router.post("/production-costs", status_code=201)
def create_batch_cost(
    data: BatchCostCreate,
    db: Session = Depends(get_db),
    current_user=Depends(require_permission("accounting", "create")),
):
    try:
        entry, jentry = pc.post_batch_cost(
            db, batch_id=data.batch_id, cost_type=data.cost_type,
            amount=Decimal(str(data.amount)) if data.amount is not None else None,
            quantity=Decimal(str(data.quantity)) if data.quantity is not None else None,
            unit=data.unit, inventory_item_id=data.inventory_item_id,
            account_id=data.account_id, reference_type=data.reference_type,
            reference_id=data.reference_id, cost_center=data.cost_center,
            notes=data.notes, cost_date=data.cost_date, created_by=current_user.id,
        )
    except pc.ProductionCostingError as exc:
        raise _fail(exc)
    db.commit()
    return {
        "id": entry.id,
        "batch_id": entry.batch_id,
        "cost_type": entry.cost_type,
        "amount": entry.amount,
        "journal_entry_id": jentry.id,
        "entry_number": jentry.entry_number,
    }


@router.get("/production-batches/{batch_id}/costing")
def get_batch_costing(
    batch_id: str,
    db: Session = Depends(get_db),
    _=Depends(require_permission("accounting", "view")),
):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")
    return pc.batch_costing_summary(db, batch)


@router.post("/production-batches/{batch_id}/ready")
def mark_batch_ready(
    batch_id: str,
    data: ReadyCreate,
    db: Session = Depends(get_db),
    current_user=Depends(require_permission("accounting", "create")),
):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")
    try:
        result = pc.mark_batch_ready(
            db, batch_id=batch.id, user_id=current_user.id,
            ready_date=data.ready_date,
            transfer_qty=Decimal(data.transfer_qty) if data.transfer_qty else None,
        )
    except pc.ProductionCostingError as exc:
        raise _fail(exc)
    db.commit()
    return result


@router.post("/production-batches/{batch_id}/mortality")
def record_batch_mortality(
    batch_id: str,
    data: MortalityCreate,
    db: Session = Depends(get_db),
    current_user=Depends(require_permission("accounting", "create")),
):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")
    try:
        result = pc.post_batch_mortality(
            db, batch_id=batch.id, user_id=current_user.id,
            quantity=Decimal(data.quantity), reason=data.reason,
            cost_date=data.cost_date,
        )
    except pc.ProductionCostingError as exc:
        raise _fail(exc)
    db.commit()
    return result


@router.get("/batch-profitability")
def batch_profitability(
    batch_id: Optional[str] = Query(default=None),
    db: Session = Depends(get_db),
    _=Depends(require_permission("accounting", "view")),
):
    rows = pc.batch_profitability_report(db, batch_id=batch_id)
    return {"batches": rows, "count": len(rows)}