from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func as sql_func
from pydantic import BaseModel
from datetime import date, datetime
from typing import Optional
from app.database import get_db
from app.models.farmer import FarmerProfile
from app.models.farm import Farm, FarmField
from app.models.customer import Customer
from app.models.plant_activation import PlantActivation, PlantCostRecord
from app.models.plant_lifecycle import PlantGrowthRecord, PlantHarvestRecord
from app.models.passport import PlantPassport
from app.services.auth import get_current_user
from app.models.user import User

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


def _generate_farmer_code(db: Session) -> str:
    year = date.today().year
    last = db.query(FarmerProfile).filter(
        FarmerProfile.id.isnot(None)
    ).order_by(FarmerProfile.created_at.desc()).first()
    if last and last.customer:
        try:
            seq = int(last.customer.code.split("-")[-1]) + 1
        except (ValueError, IndexError):
            seq = db.query(FarmerProfile).count() + 1
    else:
        seq = db.query(FarmerProfile).count() + 1
    return f"FRM-{year}-{seq:06d}"


class FarmerProfileCreate(BaseModel):
    customer_id: str
    farm_name: Optional[str] = None
    farm_area: Optional[float] = None
    land_area: Optional[float] = None
    division: Optional[str] = None
    district: Optional[str] = None
    upazila: Optional[str] = None
    union: Optional[str] = None
    village: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    profile_photo: Optional[str] = None
    farming_type: Optional[str] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None


class FarmerProfileUpdate(BaseModel):
    farm_name: Optional[str] = None
    farm_area: Optional[float] = None
    land_area: Optional[float] = None
    division: Optional[str] = None
    district: Optional[str] = None
    upazila: Optional[str] = None
    union: Optional[str] = None
    village: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    profile_photo: Optional[str] = None
    farming_type: Optional[str] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    is_verified: Optional[bool] = None
    is_active: Optional[bool] = None


class FarmerProfileOut(BaseModel):
    id: str
    customer_id: str
    customer_name: Optional[str] = None
    customer_phone: Optional[str] = None
    customer_email: Optional[str] = None
    farm_name: Optional[str] = None
    farm_area: Optional[float] = None
    land_area: Optional[float] = None
    division: Optional[str] = None
    district: Optional[str] = None
    upazila: Optional[str] = None
    union: Optional[str] = None
    village: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    profile_photo: Optional[str] = None
    farming_type: Optional[str] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    is_verified: bool
    is_active: bool
    created_at: datetime
    updated_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


@router.get("/me", response_model=FarmerProfileOut)
def get_my_farmers_profile(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    customer = db.query(Customer).filter(Customer.user_id == current_user.id).first()
    if not customer:
        raise HTTPException(status_code=404, detail="No customer profile linked to this user")
    profile = db.query(FarmerProfile).filter(FarmerProfile.customer_id == customer.id).first()
    if not profile:
        raise HTTPException(status_code=404, detail="No farmer profile linked to this user")
    return profile


@router.get("", response_model=list[FarmerProfileOut])
def list_farmers(
    search: Optional[str] = None,
    district: Optional[str] = None,
    is_verified: Optional[bool] = None,
    is_active: Optional[bool] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    q = db.query(FarmerProfile).join(Customer, FarmerProfile.customer_id == Customer.id)
    if search:
        q = q.filter(
            (Customer.name.ilike(f"%{search}%")) |
            (Customer.phone.ilike(f"%{search}%")) |
            (FarmerProfile.farm_name.ilike(f"%{search}%"))
        )
    if district:
        q = q.filter(FarmerProfile.district == district)
    if is_verified is not None:
        q = q.filter(FarmerProfile.is_verified == is_verified)
    if is_active is not None:
        q = q.filter(FarmerProfile.is_active == is_active)
    farmers = q.order_by(FarmerProfile.created_at.desc()).all()
    result = []
    for f in farmers:
        out = FarmerProfileOut.model_validate(f)
        out.customer_name = f.customer.name if f.customer else None
        out.customer_phone = f.customer.phone if f.customer else None
        out.customer_email = f.customer.email if f.customer else None
        result.append(out)
    return result


@router.post("", response_model=FarmerProfileOut)
def create_farmer_profile(
    data: FarmerProfileCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    existing = db.query(FarmerProfile).filter(FarmerProfile.customer_id == data.customer_id).first()
    if existing:
        raise HTTPException(status_code=400, detail="Farmer profile already exists for this customer")

    customer = db.query(Customer).filter(Customer.id == data.customer_id).first()
    if not customer:
        raise HTTPException(status_code=404, detail="Customer not found")

    customer.is_farmer = True
    profile = FarmerProfile(**data.model_dump())
    db.add(profile)
    db.commit()
    db.refresh(profile)

    out = FarmerProfileOut.model_validate(profile)
    out.customer_name = customer.name
    out.customer_phone = customer.phone
    out.customer_email = customer.email
    return out


@router.get("/{farmer_id}", response_model=FarmerProfileOut)
def get_farmer_profile(
    farmer_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    profile = db.query(FarmerProfile).filter(FarmerProfile.id == farmer_id).first()
    if not profile:
        raise HTTPException(status_code=404, detail="Farmer not found")
    out = FarmerProfileOut.model_validate(profile)
    out.customer_name = profile.customer.name if profile.customer else None
    out.customer_phone = profile.customer.phone if profile.customer else None
    out.customer_email = profile.customer.email if profile.customer else None
    return out


@router.put("/{farmer_id}", response_model=FarmerProfileOut)
def update_farmer_profile(
    farmer_id: str,
    data: FarmerProfileUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    profile = db.query(FarmerProfile).filter(FarmerProfile.id == farmer_id).first()
    if not profile:
        raise HTTPException(status_code=404, detail="Farmer not found")

    update_data = data.model_dump(exclude_unset=True)
    for key, value in update_data.items():
        setattr(profile, key, value)
    db.commit()
    db.refresh(profile)

    out = FarmerProfileOut.model_validate(profile)
    out.customer_name = profile.customer.name if profile.customer else None
    out.customer_phone = profile.customer.phone if profile.customer else None
    out.customer_email = profile.customer.email if profile.customer else None
    return out


@router.get("/{farmer_id}/plants")
def get_farmer_plants(
    farmer_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    profile = db.query(FarmerProfile).filter(FarmerProfile.id == farmer_id).first()
    if not profile:
        raise HTTPException(status_code=404, detail="Farmer not found")

    activations = db.query(PlantActivation).filter(PlantActivation.farmer_id == farmer_id).all()
    result = []
    for a in activations:
        passport = db.query(PlantPassport).filter(PlantPassport.id == a.passport_id).first()
        growth_count = db.query(PlantGrowthRecord).filter(PlantGrowthRecord.activation_id == a.id).count()
        harvest_count = db.query(PlantHarvestRecord).filter(PlantHarvestRecord.activation_id == a.id).count()
        total_cost = db.query(sql_func.sum(PlantCostRecord.amount)).filter(PlantCostRecord.activation_id == a.id).scalar() or 0

        result.append({
            "activation_id": a.id,
            "activation_number": a.activation_id,
            "passport_id": passport.passport_id if passport else None,
            "plant_name": passport.plant_name if passport else None,
            "variety_name": passport.variety_name if passport else None,
            "status": a.status,
            "planting_date": str(a.planting_date) if a.planting_date else None,
            "growth_records": growth_count,
            "harvest_records": harvest_count,
            "total_cost": total_cost,
        })
    return result


@router.get("/{farmer_id}/dashboard")
def get_farmer_dashboard(
    farmer_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    profile = db.query(FarmerProfile).filter(FarmerProfile.id == farmer_id).first()
    if not profile:
        raise HTTPException(status_code=404, detail="Farmer not found")

    activations = db.query(PlantActivation).filter(PlantActivation.farmer_id == farmer_id).all()
    farms = db.query(Farm).filter(Farm.farmer_id == farmer_id).all()
    fields = db.query(FarmField).join(Farm).filter(Farm.farmer_id == farmer_id).all()

    total_plants = len(activations)
    status_counts = {}
    for a in activations:
        status_counts[a.status] = status_counts.get(a.status, 0) + 1

    total_harvest = db.query(sql_func.sum(PlantHarvestRecord.revenue)).join(PlantActivation).filter(
        PlantActivation.farmer_id == farmer_id,
        PlantHarvestRecord.revenue.isnot(None)
    ).scalar() or 0

    total_cost = db.query(sql_func.sum(PlantCostRecord.amount)).join(PlantActivation).filter(
        PlantActivation.farmer_id == farmer_id
    ).scalar() or 0

    return {
        "farmer": FarmerProfileOut.model_validate(profile),
        "stats": {
            "total_plants": total_plants,
            "active_plants": status_counts.get("planted", 0) + status_counts.get("growing", 0),
            "flowering": status_counts.get("flowering", 0),
            "fruiting": status_counts.get("fruiting", 0),
            "harvesting": status_counts.get("harvesting", 0),
            "total_farms": len(farms),
            "total_fields": len(fields),
            "total_harvest_revenue": total_harvest,
            "total_cost": total_cost,
            "profit": total_harvest - total_cost,
        },
        "status_breakdown": status_counts,
    }
