from __future__ import annotations
import uuid
from datetime import datetime, date
from typing import Optional
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.plant import PlantCategory, PlantVariety, Plant
from app.services.auth import get_current_user

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


class CategoryCreate(BaseModel):
    name: str
    description: Optional[str] = None
    icon: Optional[str] = None

class CategoryUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    icon: Optional[str] = None

class CategoryOut(BaseModel):
    id: str
    name: str
    description: Optional[str] = None
    icon: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class VarietyCreate(BaseModel):
    name: str
    category_id: str
    plant_type: str = "Outdoor"
    life_cycle: Optional[str] = None
    growing_season: Optional[str] = None
    sunlight: Optional[str] = None
    water_requirement: Optional[str] = None
    soil_type: Optional[str] = None

class VarietyUpdate(BaseModel):
    name: Optional[str] = None
    category_id: Optional[str] = None
    plant_type: Optional[str] = None
    life_cycle: Optional[str] = None
    growing_season: Optional[str] = None
    sunlight: Optional[str] = None
    water_requirement: Optional[str] = None
    soil_type: Optional[str] = None

class VarietyOut(BaseModel):
    id: str
    name: str
    category_id: str
    plant_type: str
    life_cycle: Optional[str] = None
    growing_season: Optional[str] = None
    sunlight: Optional[str] = None
    water_requirement: Optional[str] = None
    soil_type: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class PlantCreate(BaseModel):
    name: str
    scientific_name: Optional[str] = None
    local_name: Optional[str] = None
    variety_id: Optional[str] = None
    description: Optional[str] = None
    fertilizer_schedule: Optional[str] = None
    pest_info: Optional[str] = None
    care_instructions: Optional[str] = None
    retail_price: float = 0.0
    wholesale_price: float = 0.0
    dealer_price: float = 0.0
    barcode: Optional[str] = None
    image_url: Optional[str] = None
    is_active: bool = True

class PlantUpdate(BaseModel):
    name: Optional[str] = None
    scientific_name: Optional[str] = None
    local_name: Optional[str] = None
    variety_id: Optional[str] = None
    description: Optional[str] = None
    fertilizer_schedule: Optional[str] = None
    pest_info: Optional[str] = None
    care_instructions: Optional[str] = None
    retail_price: Optional[float] = None
    wholesale_price: Optional[float] = None
    dealer_price: Optional[float] = None
    barcode: Optional[str] = None
    image_url: Optional[str] = None
    is_active: Optional[bool] = None

class PlantOut(BaseModel):
    id: str
    code: str
    name: str
    scientific_name: Optional[str] = None
    local_name: Optional[str] = None
    variety_id: Optional[str] = None
    description: Optional[str] = None
    fertilizer_schedule: Optional[str] = None
    pest_info: Optional[str] = None
    care_instructions: Optional[str] = None
    retail_price: float
    wholesale_price: float
    dealer_price: float
    barcode: Optional[str] = None
    image_url: Optional[str] = None
    is_active: bool
    created_at: datetime
    updated_at: datetime
    model_config = {"from_attributes": True}

class PaginatedPlantOut(BaseModel):
    items: list[PlantOut]
    total: int
    page: int
    page_size: int
    pages: int


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


@router.get("/categories", response_model=list[CategoryOut])
def list_categories(db: Session = Depends(get_db), _=Depends(get_current_user)):
    return db.query(PlantCategory).order_by(PlantCategory.name).all()


@router.post("/categories", response_model=CategoryOut, status_code=201)
def create_category(data: CategoryCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    existing = db.query(PlantCategory).filter(PlantCategory.name == data.name).first()
    if existing:
        raise HTTPException(status_code=400, detail="Category name already exists")
    obj = PlantCategory(**data.model_dump())
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/categories/{category_id}", response_model=CategoryOut)
def get_category(category_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantCategory).filter(PlantCategory.id == category_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Category not found")
    return obj


@router.put("/categories/{category_id}", response_model=CategoryOut)
def update_category(category_id: str, data: CategoryUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantCategory).filter(PlantCategory.id == category_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Category 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("/categories/{category_id}")
def delete_category(category_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantCategory).filter(PlantCategory.id == category_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Category not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Category deleted"}


@router.get("/varieties", response_model=list[VarietyOut])
def list_varieties(
    category_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(PlantVariety)
    if category_id:
        q = q.filter(PlantVariety.category_id == category_id)
    return q.order_by(PlantVariety.name).all()


@router.post("/varieties", response_model=VarietyOut, status_code=201)
def create_variety(data: VarietyCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    cat = db.query(PlantCategory).filter(PlantCategory.id == data.category_id).first()
    if not cat:
        raise HTTPException(status_code=404, detail="Category not found")
    obj = PlantVariety(**data.model_dump())
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/varieties/{variety_id}", response_model=VarietyOut)
def get_variety(variety_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantVariety).filter(PlantVariety.id == variety_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Variety not found")
    return obj


@router.put("/varieties/{variety_id}", response_model=VarietyOut)
def update_variety(variety_id: str, data: VarietyUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantVariety).filter(PlantVariety.id == variety_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Variety 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("/varieties/{variety_id}")
def delete_variety(variety_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(PlantVariety).filter(PlantVariety.id == variety_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Variety not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Variety deleted"}


class PlantSummary(BaseModel):
    id: str
    code: str
    name: str
    scientific_name: Optional[str] = None
    model_config = {"from_attributes": True}


@router.get("", response_model=PaginatedPlantOut)
def list_plants(
    variety_id: Optional[str] = None,
    is_active: Optional[bool] = None,
    search: Optional[str] = None,
    page: int = 1,
    page_size: int = 50,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(Plant)
    if variety_id:
        q = q.filter(Plant.variety_id == variety_id)
    if is_active is not None:
        q = q.filter(Plant.is_active == is_active)
    if search:
        q = q.filter(Plant.name.ilike(f"%{search}%"))
    total = q.count()
    pages = max(1, (total + page_size - 1) // page_size)
    items = q.order_by(Plant.name).offset((page - 1) * page_size).limit(page_size).all()
    return PaginatedPlantOut(items=items, total=total, page=page, page_size=page_size, pages=pages)


@router.get("/dropdown", response_model=list[PlantSummary])
def list_plants_dropdown(
    search: Optional[str] = None,
    page: int = 1,
    page_size: int = 50,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(Plant).filter(Plant.is_active == True)
    if search:
        q = q.filter(Plant.name.ilike(f"%{search}%"))
    return q.order_by(Plant.name).offset((page - 1) * page_size).limit(page_size).all()


@router.post("", response_model=PlantOut, status_code=201)
def create_plant(data: PlantCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = Plant(**data.model_dump(), code=_generate_plant_code(db))
    db.add(obj)
    db.commit()
    db.refresh(obj)
    return obj


@router.get("/{plant_id}", response_model=PlantOut)
def get_plant(plant_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(Plant).filter(Plant.id == plant_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Plant not found")
    return obj


@router.put("/{plant_id}", response_model=PlantOut)
def update_plant(plant_id: str, data: PlantUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(Plant).filter(Plant.id == plant_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Plant 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("/{plant_id}")
def delete_plant(plant_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(Plant).filter(Plant.id == plant_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Plant not found")
    db.delete(obj)
    db.commit()
    return {"detail": "Plant deleted"}
