from __future__ import annotations
from datetime import datetime
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.alert import Alert, Notification
from app.services.auth import get_current_user

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


class AlertOut(BaseModel):
    id: str
    alert_type: str
    title: str
    message: Optional[str] = None
    severity: str
    is_resolved: bool
    reference_type: Optional[str] = None
    reference_id: Optional[str] = None
    created_at: datetime
    resolved_at: Optional[datetime] = None
    model_config = {"from_attributes": True}

class NotificationOut(BaseModel):
    id: str
    user_id: Optional[str] = None
    title: str
    message: Optional[str] = None
    type: str
    is_read: bool
    link: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}


@router.get("", response_model=list[AlertOut])
def list_alerts(
    is_resolved: Optional[bool] = None,
    severity: Optional[str] = None,
    alert_type: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(Alert)
    if is_resolved is not None:
        q = q.filter(Alert.is_resolved == is_resolved)
    if severity:
        q = q.filter(Alert.severity == severity)
    if alert_type:
        q = q.filter(Alert.alert_type == alert_type)
    return q.order_by(Alert.created_at.desc()).all()


@router.get("/unread-count")
def unread_count(db: Session = Depends(get_db), _=Depends(get_current_user)):
    count = db.query(func.count(Alert.id)).filter(Alert.is_resolved == False).scalar() or 0
    return {"count": count}


@router.patch("/{alert_id}/resolve")
def resolve_alert(alert_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    obj = db.query(Alert).filter(Alert.id == alert_id).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Alert not found")
    obj.is_resolved = True
    obj.resolved_at = datetime.utcnow()
    db.commit()
    return {"detail": "Alert resolved"}


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


@router.get("/notifications", response_model=list[NotificationOut])
def list_notifications(
    is_read: Optional[bool] = None,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user),
):
    q = db.query(Notification).filter(Notification.user_id == current_user.id)
    if is_read is not None:
        q = q.filter(Notification.is_read == is_read)
    return q.order_by(Notification.created_at.desc()).all()


@router.get("/notifications/unread-count")
def notifications_unread_count(db: Session = Depends(get_db), current_user=Depends(get_current_user)):
    count = db.query(func.count(Notification.id)).filter(
        Notification.user_id == current_user.id,
        Notification.is_read == False,
    ).scalar() or 0
    return {"count": count}


@router.patch("/notifications/{notification_id}/read")
def mark_notification_read(notification_id: str, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
    obj = db.query(Notification).filter(
        Notification.id == notification_id,
        Notification.user_id == current_user.id,
    ).first()
    if not obj:
        raise HTTPException(status_code=404, detail="Notification not found")
    obj.is_read = True
    db.commit()
    return {"detail": "Notification marked as read"}


@router.patch("/notifications/mark-all-read")
def mark_all_notifications_read(db: Session = Depends(get_db), current_user=Depends(get_current_user)):
    db.query(Notification).filter(
        Notification.user_id == current_user.id,
        Notification.is_read == False,
    ).update({"is_read": True})
    db.commit()
    return {"detail": "All notifications marked as read"}


class NotificationCreate(BaseModel):
    user_id: str
    title: str
    message: Optional[str] = None
    type: str = "info"
    link: Optional[str] = None


@router.post("/notifications", status_code=201)
def create_notification(data: NotificationCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    n = Notification(
        user_id=data.user_id,
        title=data.title,
        message=data.message,
        type=data.type,
        link=data.link,
    )
    db.add(n)
    db.commit()
    db.refresh(n)
    return {
        "id": n.id,
        "user_id": n.user_id,
        "title": n.title,
        "message": n.message,
        "type": n.type,
        "is_read": n.is_read,
        "link": n.link,
        "created_at": n.created_at.isoformat() if n.created_at else None,
    }


@router.post("/notifications/generate")
def generate_notifications(db: Session = Depends(get_db), _=Depends(get_current_user)):
    from datetime import date, timedelta
    from app.models.plant_lifecycle import PlantCareSchedule
    from app.models.plant_activation import PlantActivation
    from app.models.passport import PlantPassport
    from app.models.farm import Farm
    from app.models.farmer import FarmerProfile

    today = date.today()
    created = 0

    schedules = db.query(PlantCareSchedule).join(PlantActivation).filter(
        PlantCareSchedule.is_active == True,
        PlantCareSchedule.next_due_date <= today + timedelta(days=1),
    ).all()

    for s in schedules:
        activation = db.query(PlantActivation).filter(PlantActivation.id == s.activation_id).first()
        if not activation:
            continue
        passport = db.query(PlantPassport).filter(PlantPassport.id == activation.passport_id).first()
        farmer = db.query(FarmerProfile).filter(FarmerProfile.id == activation.farmer_id).first()
        if not farmer or not passport:
            continue

        customer = None
        try:
            from app.models.customer import Customer
            customer = db.query(Customer).filter(Customer.id == farmer.customer_id).first()
        except Exception:
            pass

        user_id = getattr(customer, 'user_id', None) if customer else None
        if not user_id:
            continue

        is_overdue = s.next_due_date < today
        days_diff = (today - s.next_due_date).days if s.next_due_date else 0

        care_labels = {
            "watering": "Watering",
            "fertilizing": "Fertilizer",
            "pruning": "Pruning",
            "spraying": "Spray/Treatment",
            "inspection": "Inspection",
        }
        care_label = care_labels.get(s.care_type, s.care_type)

        existing = db.query(Notification).filter(
            Notification.user_id == user_id,
            Notification.type.in_(["care_due", "care_overdue"]),
        ).join(Notification, Notification.title.ilike(f"%{care_label}%{passport.plant_name}%")).first()

        if is_overdue:
            title = f"{care_label} overdue for {passport.plant_name}"
            message = f"{care_label} was due {days_diff} day(s) ago. Please take action."
            ntype = "care_overdue"
            link = f"/farmer/tasks"
        else:
            title = f"{care_label} due today for {passport.plant_name}"
            message = f"{care_label} is scheduled for today. Don't forget!"
            ntype = "care_due"
            link = f"/farmer/tasks"

        existing_check = db.query(Notification).filter(
            Notification.user_id == user_id,
            Notification.title == title,
        ).first()

        if existing_check:
            continue

        n = Notification(
            user_id=user_id,
            title=title,
            message=message,
            type=ntype,
            link=link,
        )
        db.add(n)
        created += 1

    harvest_plants = db.query(PlantActivation).filter(
        PlantActivation.status.in_(["activated", "planted"]),
    ).all()

    for act in harvest_plants:
        passport = db.query(PlantPassport).filter(PlantPassport.id == act.passport_id).first()
        farmer = db.query(FarmerProfile).filter(FarmerProfile.id == act.farmer_id).first()
        if not farmer or not passport:
            continue

        customer = None
        try:
            from app.models.customer import Customer
            customer = db.query(Customer).filter(Customer.id == farmer.customer_id).first()
        except Exception:
            pass

        user_id = getattr(customer, 'user_id', None) if customer else None
        if not user_id:
            continue

        if act.planting_date and (today - act.planting_date).days >= 45:
            title = f"Harvest window approaching for {passport.plant_name}"
            message = f"This plant was activated {(today - act.planting_date).days} days ago. Consider harvesting soon."
            link = f"/farmer/plants/{act.id}"

            existing_check = db.query(Notification).filter(
                Notification.user_id == user_id,
                Notification.title == title,
            ).first()

            if not existing_check:
                n = Notification(
                    user_id=user_id,
                    title=title,
                    message=message,
                    type="harvest_reminder",
                    link=link,
                )
                db.add(n)
                created += 1

    db.commit()
    return {"created": created, "message": f"Generated {created} notification(s)"}
