from __future__ import annotations
import uuid
from datetime import datetime, date
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func
from pydantic import BaseModel
from app.database import get_db
from app.models.production import SeedLot, ProductionBatch, GerminationRecord, TransplantRecord
from app.models.plant import Plant
from app.services.auth import get_current_user

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


class SeedLotCreate(BaseModel):
    lot_number: str
    plant_id: str
    supplier_id: Optional[str] = None
    quantity: int = 0
    unit: str = "grams"
    purchase_date: Optional[date] = None
    expiry_date: Optional[date] = None
    cost_per_unit: float = 0.0
    notes: Optional[str] = None

class SeedLotUpdate(BaseModel):
    lot_number: Optional[str] = None
    plant_id: Optional[str] = None
    supplier_id: Optional[str] = None
    quantity: Optional[int] = None
    unit: Optional[str] = None
    purchase_date: Optional[date] = None
    expiry_date: Optional[date] = None
    cost_per_unit: Optional[float] = None
    notes: Optional[str] = None

class SeedLotOut(BaseModel):
    id: str
    lot_number: str
    plant_id: str
    supplier_id: Optional[str] = None
    quantity: int
    unit: str
    purchase_date: Optional[date] = None
    expiry_date: Optional[date] = None
    cost_per_unit: float
    notes: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class BatchCreate(BaseModel):
    plant_id: str
    seed_lot_id: Optional[str] = None
    sowing_date: date
    expected_ready_date: Optional[date] = None
    sown_quantity: int = 0
    current_quantity: int = 0
    status: str = "sowing"
    tray_number: Optional[str] = None
    location: Optional[str] = None
    employee_id: Optional[str] = None
    notes: Optional[str] = None

class BatchUpdate(BaseModel):
    batch_number: Optional[str] = None
    plant_id: Optional[str] = None
    seed_lot_id: Optional[str] = None
    sowing_date: Optional[date] = None
    expected_ready_date: Optional[date] = None
    sown_quantity: Optional[int] = None
    current_quantity: Optional[int] = None
    status: Optional[str] = None
    tray_number: Optional[str] = None
    location: Optional[str] = None
    employee_id: Optional[str] = None
    notes: Optional[str] = None

class BatchOut(BaseModel):
    id: str
    batch_number: str
    plant_id: str
    seed_lot_id: Optional[str] = None
    sowing_date: date
    expected_ready_date: Optional[date] = None
    sown_quantity: int
    current_quantity: int
    status: str
    tray_number: Optional[str] = None
    location: Optional[str] = None
    employee_id: Optional[str] = None
    notes: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    model_config = {"from_attributes": True}

class GerminationCreate(BaseModel):
    batch_id: str
    date: date
    germinated_quantity: int = 0
    notes: Optional[str] = None

class GerminationOut(BaseModel):
    id: str
    batch_id: str
    date: date
    germinated_quantity: int
    success_rate: float
    notes: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class TransplantCreate(BaseModel):
    batch_id: str
    date: date
    from_container: str
    to_container: str
    quantity: int = 0
    employee_id: Optional[str] = None
    notes: Optional[str] = None

class TransplantOut(BaseModel):
    id: str
    batch_id: str
    date: date
    from_container: str
    to_container: str
    quantity: int
    employee_id: Optional[str] = None
    notes: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}


def _generate_batch_number(db: Session) -> str:
    year = datetime.now().year
    last = db.query(ProductionBatch).filter(
        ProductionBatch.batch_number.like(f"BAT-{year}-%")
    ).order_by(ProductionBatch.batch_number.desc()).first()
    if last:
        seq = int(last.batch_number.split("-")[-1]) + 1
    else:
        seq = 1
    return f"BAT-{year}-{seq:06d}"


@router.get("/seed-lots", response_model=list[SeedLotOut])
def list_seed_lots(
    plant_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(SeedLot)
    if plant_id:
        q = q.filter(SeedLot.plant_id == plant_id)
    return q.order_by(SeedLot.created_at.desc()).all()


@router.post("/seed-lots", response_model=SeedLotOut, status_code=201)
def create_seed_lot(data: SeedLotCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    plant = db.query(Plant).filter(Plant.id == data.plant_id).first()
    if not plant:
        raise HTTPException(status_code=404, detail="Plant not found")
    obj = SeedLot(**data.model_dump())
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/seed-lots/{seed_lot_id}", response_model=SeedLotOut)
def get_seed_lot(seed_lot_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(SeedLot).filter(SeedLot.id == seed_lot_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Seed lot not found")
    return obj


@router.put("/seed-lots/{seed_lot_id}", response_model=SeedLotOut)
def update_seed_lot(seed_lot_id: str, data: SeedLotUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(SeedLot).filter(SeedLot.id == seed_lot_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Seed lot not found")
    for k, v in data.model_dump(exclude_unset=True).items():
        setattr(obj, k, v)
    db.commit()
    db.refresh(obj)
    return obj


@router.delete("/seed-lots/{seed_lot_id}")
def delete_seed_lot(seed_lot_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(SeedLot).filter(SeedLot.id == seed_lot_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Seed lot not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Seed lot deleted"}


@router.get("/batches", response_model=list[BatchOut])
def list_batches(
    plant_id: Optional[str] = None,
    status: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(ProductionBatch)
    if plant_id:
        q = q.filter(ProductionBatch.plant_id == plant_id)
    if status:
        q = q.filter(ProductionBatch.status == status)
    return q.order_by(ProductionBatch.created_at.desc()).all()


@router.post("/batches", response_model=BatchOut, status_code=201)
def create_batch(data: BatchCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    plant = db.query(Plant).filter(Plant.id == data.plant_id).first()
    if not plant:
        raise HTTPException(status_code=404, detail="Plant not found")
    batch_data = data.model_dump()
    if not batch_data.get("current_quantity"):
        batch_data["current_quantity"] = batch_data.get("sown_quantity", 0)
    obj = ProductionBatch(**batch_data, batch_number=_generate_batch_number(db))
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/batches/{batch_id}", response_model=BatchOut)
def get_batch(batch_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Batch not found")
    return obj


@router.put("/batches/{batch_id}", response_model=BatchOut)
def update_batch(batch_id: str, data: BatchUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Batch not found")
    for k, v in data.model_dump(exclude_unset=True).items():
        setattr(obj, k, v)
    db.commit()
    db.refresh(obj)
    return obj


@router.delete("/batches/{batch_id}")
def delete_batch(batch_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(ProductionBatch).filter(ProductionBatch.id == batch_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Batch not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Batch deleted"}


@router.get("/germination", response_model=list[GerminationOut])
def list_germination(
    batch_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(GerminationRecord)
    if batch_id:
        q = q.filter(GerminationRecord.batch_id == batch_id)
    return q.order_by(GerminationRecord.created_at.desc()).all()


@router.post("/germination", response_model=GerminationOut, status_code=201)
def create_germination(data: GerminationCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == data.batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")
    success_rate = 0.0
    if batch.sown_quantity > 0:
        success_rate = round((data.germinated_quantity / batch.sown_quantity) * 100, 2)
    obj = GerminationRecord(**data.model_dump(), success_rate=success_rate)
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/germination/{record_id}", response_model=GerminationOut)
def get_germination(record_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(GerminationRecord).filter(GerminationRecord.id == record_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Germination record not found")
    return obj


@router.delete("/germination/{record_id}")
def delete_germination(record_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(GerminationRecord).filter(GerminationRecord.id == record_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Germination record not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Germination record deleted"}


@router.get("/transplants", response_model=list[TransplantOut])
def list_transplants(
    batch_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(TransplantRecord)
    if batch_id:
        q = q.filter(TransplantRecord.batch_id == batch_id)
    return q.order_by(TransplantRecord.created_at.desc()).all()


@router.post("/transplants", response_model=TransplantOut, status_code=201)
def create_transplant(data: TransplantCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == data.batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")
    obj = TransplantRecord(**data.model_dump())
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/transplants/{record_id}", response_model=TransplantOut)
def get_transplant(record_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(TransplantRecord).filter(TransplantRecord.id == record_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Transplant record not found")
    return obj


@router.delete("/transplants/{record_id}")
def delete_transplant(record_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(TransplantRecord).filter(TransplantRecord.id == record_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Transplant record not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Transplant record deleted"}
