# app/modules/procurement/engine_routes.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from typing import List, Optional
from uuid import UUID
from datetime import datetime

from app.core.database import get_db
from app.core.security import require_permission
from .engine_service import ProcurementEngineService
from app.models.procurement_models import RmPurchaseRequest
from pydantic import BaseModel
from decimal import Decimal

# ── Local schemas (never existed in procurement/schemas.py) ──────────────────
class ChassisMoveRequest(BaseModel):
    chassis_ids: List[UUID]  # BUG-04 FIX: was chassis_id (singular)

class BomItemSimulation(BaseModel):
    rm_id: UUID
    rm_code: Optional[str] = None
    rm_name: Optional[str] = None
    station_name: Optional[str] = None
    unit_of_measure: Optional[str] = "NOS"
    required_qty: float
    available_qty: float
    shortage_qty: float
    supplier_name: Optional[str] = "—"
    received_rm_qty: Optional[float] = 0.0
    pending_po_qty: Optional[float] = 0.0
    expected_delivery_date: Optional[str] = None
    category: Optional[str] = None

class ProcurementSimulationResponse(BaseModel):
    chassis_id: UUID
    chassis_number: Optional[str] = None
    chassis_no: Optional[str] = None
    can_proceed: bool
    has_covered_shortages: Optional[bool] = False
    bom_items: List[BomItemSimulation] = []

class BomLineConfirm(BaseModel):
    rm_id: UUID
    qty: Decimal

class BulkProcurementRequest(BaseModel):
    chassis_ids: List[UUID]

class AssignVendorRequest(BaseModel):
    vendor_id: UUID

class ProcurementConfirmRequest(BaseModel):
    chassis_id: UUID
    final_bom: List[BomLineConfirm] = []

class RmPurchaseRequestDetailResponse(BaseModel):
    request_detail_id: UUID
    rm_id: UUID
    rm_name: Optional[str] = None
    shortage_qty: Decimal

    class Config:
        from_attributes = True

class RmPurchaseRequestResponse(BaseModel):
    request_id: UUID
    request_number: Optional[str] = None
    vendor_id: Optional[UUID] = None
    chassis_id: Optional[UUID] = None
    status: Optional[str] = None
    created_at: Optional[datetime] = None
    details: List[RmPurchaseRequestDetailResponse] = []

    class Config:
        from_attributes = True

router = APIRouter()

@router.post('/chassis/move-to-check', status_code=200)
async def move_to_check(
    data: ChassisMoveRequest,
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PRODUCTION', 'edit'))
):
    """Production moves chassis to the procurement check queue."""
    service = ProcurementEngineService(db)
    await service.move_to_check(data.chassis_ids)
    await db.commit()
    return {"message": f"{len(data.chassis_ids)} chassis moved to procurement queue."}

@router.get('/chassis/queue')
async def get_queue(
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Fetch the queue of chassis currently in Procurement Engine."""
    service = ProcurementEngineService(db)
    queue = await service.get_queue()
    
    return [
        {
            "chassis_id": c.chassis_id,
            "chassis_no": c.chassis_no,
            "procurement_status": c.procurement_status,
            "dealer_order_vehicle": {
                "model": {"model_number": c.dealer_order_vehicle.model.model_number} if c.dealer_order_vehicle and getattr(c.dealer_order_vehicle, 'model', None) else None,
                "body_type": {"name": c.dealer_order_vehicle.body_type.name} if c.dealer_order_vehicle and getattr(c.dealer_order_vehicle, 'body_type', None) else None,
                "segment": {"name": c.dealer_order_vehicle.segment.name} if c.dealer_order_vehicle and getattr(c.dealer_order_vehicle, 'segment', None) else None
            } if getattr(c, 'dealer_order_vehicle', None) else {
                "model": {"model_number": c.model.model_number} if getattr(c, 'model', None) else None,
                "body_type": None,
                "segment": None
            }
        }
        for c in queue
    ]

@router.get('/chassis/{chassis_id}/simulate', response_model=ProcurementSimulationResponse)
async def simulate_check(
    chassis_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Explode BOM and simulate against current stock."""
    service = ProcurementEngineService(db)
    return await service.simulate_check(chassis_id)

@router.post('/chassis/{chassis_id}/confirm')
async def confirm_reservation(
    chassis_id: UUID,
    data: ProcurementConfirmRequest,
    db: AsyncSession = Depends(get_db),
    user=Depends(require_permission('PROCUREMENT', 'edit'))
):
    """Confirm reservation with the finalized/edited BOM payload.
    
    FLAW-01 FIX: Explicit commit/rollback wrapping.
    """
    if chassis_id != data.chassis_id:
        raise HTTPException(400, "Chassis ID mismatch")
    
    service = ProcurementEngineService(db)
    try:
        await service.confirm_reservation(chassis_id, data.final_bom, user.user_id)
        await db.commit()
    except HTTPException:
        await db.rollback()
        raise
    except Exception as e:
        await db.rollback()
        raise HTTPException(500, f"Reservation failed: {str(e)}")
    return {"message": "Reservation confirmed"}

@router.post('/requests/{request_id}/details/{detail_id}/assign')
async def assign_vendor(
    request_id: UUID, 
    detail_id: UUID, 
    req: AssignVendorRequest, 
    db: AsyncSession = Depends(get_db), 
    user=Depends(require_permission('PROCUREMENT', 'edit'))
):
    """Assign an unassigned PR detail to a specific vendor PR."""
    service = ProcurementEngineService(db)
    await service.assign_vendor_to_pr_detail(request_id, detail_id, req.vendor_id, user.user_id)
    return {"status": "success"}

@router.get('/rm/{rm_id}/vendors')
async def get_rm_vendors(
    rm_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Get vendors mapped to an RM with their standard costs."""
    from app.models.rm_models import RmVendorMapping, VendorMaster
    stmt = select(RmVendorMapping, VendorMaster).join(VendorMaster, RmVendorMapping.vendor_id == VendorMaster.vendor_id).where(RmVendorMapping.rm_id == rm_id)
    res = await db.execute(stmt)
    return [{"vendor_id": v.vendor_id, "vendor_name": v.name, "standard_cost": m.standard_cost} for m, v in res.all()]

@router.get('/requests', response_model=List[RmPurchaseRequestResponse])
async def get_requests(
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Fetch active Purchase Requests (Indents)."""
    stmt = (
        select(RmPurchaseRequest)
        .options(selectinload(RmPurchaseRequest.details))
        .order_by(RmPurchaseRequest.created_at.desc())
    )
    result = await db.execute(stmt)
    return list(result.scalars().all())

@router.delete('/requests/{request_id}', status_code=204)
async def delete_purchase_request(
    request_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'delete'))
):
    """Delete a Purchase Request manually."""
    stmt = select(RmPurchaseRequest).where(RmPurchaseRequest.request_id == request_id)
    result = await db.execute(stmt)
    pr = result.scalar_one_or_none()
    
    if not pr:
        raise HTTPException(status_code=404, detail="Purchase Request not found")
        
    await db.delete(pr)
    await db.flush()

@router.get('/chassis/confirmed')
async def get_confirmed_queue(
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Fetch chassis that have completed procurement check."""
    service = ProcurementEngineService(db)
    queue = await service.get_confirmed_queue()
    return [
        {
            "chassis_id": c.chassis_id,
            "chassis_no": c.chassis_no,
            "procurement_status": c.procurement_status,
            "dealer_order_vehicle": {
                "model": {"model_number": c.dealer_order_vehicle.model.model_number} if c.dealer_order_vehicle and c.dealer_order_vehicle.model else None,
                "body_type": {"name": c.dealer_order_vehicle.body_type.name} if c.dealer_order_vehicle and c.dealer_order_vehicle.body_type else None,
                "segment": {"name": c.dealer_order_vehicle.segment.name} if c.dealer_order_vehicle and c.dealer_order_vehicle.segment else None
            } if c.dealer_order_vehicle else None
        }
        for c in queue
    ]

@router.get('/chassis/backflush-queue')
async def get_backflush_queue(
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Fetch chassis currently in production (WIP) for backflush review."""
    service = ProcurementEngineService(db)
    queue = await service.get_backflush_queue()
    return [
        {
            "chassis_id": c.chassis_id,
            "chassis_no": c.chassis_no,
            "procurement_status": c.procurement_status,
            "dealer_order_vehicle": {
                "model": {"model_number": c.dealer_order_vehicle.model.model_number} if c.dealer_order_vehicle and c.dealer_order_vehicle.model else None,
                "body_type": {"name": c.dealer_order_vehicle.body_type.name} if c.dealer_order_vehicle and c.dealer_order_vehicle.body_type else None,
                "segment": {"name": c.dealer_order_vehicle.segment.name} if c.dealer_order_vehicle and c.dealer_order_vehicle.segment else None
            } if c.dealer_order_vehicle else None
        }
        for c in queue
    ]

@router.get('/chassis/{chassis_id}/bom')
async def get_chassis_bom(
    chassis_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(require_permission('PROCUREMENT', 'view'))
):
    """Fetch the confirmed BOM snapshot for a chassis, grouped by station."""
    service = ProcurementEngineService(db)
    return await service.get_chassis_bom(chassis_id)

class AdhocIssueRequest(BaseModel):
    rm_id: UUID
    qty: Decimal
    station_id: Optional[UUID] = None   # BUG-06 FIX: include station_id and category
    category: Optional[str] = "Ad-hoc"

@router.post('/chassis/{chassis_id}/adhoc-issue')
async def issue_adhoc_rm(
    chassis_id: UUID,
    data: AdhocIssueRequest,
    db: AsyncSession = Depends(get_db),
    user=Depends(require_permission('PROCUREMENT', 'edit'))
):
    """Manually issue raw materials to a chassis."""
    service = ProcurementEngineService(db)
    try:
        result = await service.issue_adhoc_rm(
            chassis_id, data.rm_id, data.qty, user.user_id,
            station_id=data.station_id, category=data.category
        )
        await db.commit()
        return result
    except HTTPException:
        await db.rollback()
        raise
    except Exception as e:
        await db.rollback()
        raise HTTPException(500, f"Ad-hoc issue failed: {str(e)}")
