from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from datetime import date, datetime
from typing import Optional
from app.database import get_db
from app.models.farm import Farm, FarmField
from app.models.farmer import FarmerProfile
from app.services.auth import get_current_user
from app.models.user import User

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


class FarmCreate(BaseModel):
    farmer_id: str
    name: str
    area: Optional[float] = None
    address: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    farming_type: Optional[str] = None
    notes: Optional[str] = None


class FarmUpdate(BaseModel):
    name: Optional[str] = None
    area: Optional[float] = None
    address: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    farming_type: Optional[str] = None
    notes: Optional[str] = None
    is_active: Optional[bool] = None


class FarmOut(BaseModel):
    id: str
    farmer_id: str
    name: str
    area: Optional[float] = None
    address: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    farming_type: Optional[str] = None
    notes: Optional[str] = None
    is_active: bool
    created_at: datetime
    updated_at: Optional[datetime] = None
    field_count: int = 0

    model_config = {"from_attributes": True}


class FieldCreate(BaseModel):
    farm_id: str
    name: str
    area: Optional[float] = None
    crop_type: Optional[str] = None
    plant_count: int = 0
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    planting_date: Optional[date] = None
    status: str = "active"


class FieldUpdate(BaseModel):
    name: Optional[str] = None
    area: Optional[float] = None
    crop_type: Optional[str] = None
    plant_count: Optional[int] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    planting_date: Optional[date] = None
    status: Optional[str] = None


class FieldOut(BaseModel):
    id: str
    farm_id: str
    name: str
    area: Optional[float] = None
    crop_type: Optional[str] = None
    plant_count: int
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    soil_type: Optional[str] = None
    irrigation_type: Optional[str] = None
    planting_date: Optional[date] = None
    status: str
    created_at: datetime
    updated_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


@router.get("", response_model=list[FarmOut])
def list_farms(
    farmer_id: Optional[str] = None,
    is_active: Optional[bool] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    q = db.query(Farm)
    if farmer_id:
        q = q.filter(Farm.farmer_id == farmer_id)
    if is_active is not None:
        q = q.filter(Farm.is_active == is_active)
    farms = q.order_by(Farm.created_at.desc()).all()
    result = []
    for f in farms:
        out = FarmOut.model_validate(f)
        out.field_count = db.query(FarmField).filter(FarmField.farm_id == f.id).count()
        result.append(out)
    return result


@router.post("", response_model=FarmOut)
def create_farm(
    data: FarmCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farmer = db.query(FarmerProfile).filter(FarmerProfile.id == data.farmer_id).first()
    if not farmer:
        raise HTTPException(status_code=404, detail="Farmer not found")

    farm = Farm(**data.model_dump())
    db.add(farm)
    db.commit()
    db.refresh(farm)

    out = FarmOut.model_validate(farm)
    out.field_count = 0
    return out


@router.get("/{farm_id}", response_model=FarmOut)
def get_farm(
    farm_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")
    out = FarmOut.model_validate(farm)
    out.field_count = db.query(FarmField).filter(FarmField.farm_id == farm.id).count()
    return out


@router.put("/{farm_id}", response_model=FarmOut)
def update_farm(
    farm_id: str,
    data: FarmUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")

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

    out = FarmOut.model_validate(farm)
    out.field_count = db.query(FarmField).filter(FarmField.farm_id == farm.id).count()
    return out


@router.delete("/{farm_id}")
def delete_farm(
    farm_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")
    db.delete(farm)
    db.commit()
    return {"detail": "Farm deleted"}


@router.get("/{farm_id}/fields", response_model=list[FieldOut])
def list_farm_fields(
    farm_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")
    fields = db.query(FarmField).filter(FarmField.farm_id == farm_id).order_by(FarmField.name).all()
    return [FieldOut.model_validate(f) for f in fields]


@router.get("/{farm_id}/map")
def get_farm_map(
    farm_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")

    fields = db.query(FarmField).filter(FarmField.farm_id == farm_id).all()
    return {
        "farm": {
            "id": farm.id,
            "name": farm.name,
            "latitude": farm.latitude,
            "longitude": farm.longitude,
            "area": farm.area,
        },
        "fields": [
            {
                "id": f.id,
                "name": f.name,
                "latitude": f.latitude,
                "longitude": f.longitude,
                "area": f.area,
                "status": f.status,
                "plant_count": f.plant_count,
            }
            for f in fields
        ],
    }


@router.post("/fields", response_model=FieldOut)
def create_field(
    data: FieldCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    farm = db.query(Farm).filter(Farm.id == data.farm_id).first()
    if not farm:
        raise HTTPException(status_code=404, detail="Farm not found")

    field = FarmField(**data.model_dump())
    db.add(field)
    db.commit()
    db.refresh(field)
    return FieldOut.model_validate(field)


@router.get("/fields/{field_id}", response_model=FieldOut)
def get_field(
    field_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    field = db.query(FarmField).filter(FarmField.id == field_id).first()
    if not field:
        raise HTTPException(status_code=404, detail="Field not found")
    return FieldOut.model_validate(field)


@router.put("/fields/{field_id}", response_model=FieldOut)
def update_field(
    field_id: str,
    data: FieldUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    field = db.query(FarmField).filter(FarmField.id == field_id).first()
    if not field:
        raise HTTPException(status_code=404, detail="Field not found")

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


@router.delete("/fields/{field_id}")
def delete_field(
    field_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    field = db.query(FarmField).filter(FarmField.id == field_id).first()
    if not field:
        raise HTTPException(status_code=404, detail="Field not found")
    db.delete(field)
    db.commit()
    return {"detail": "Field deleted"}
