"""
Daily Helper API endpoints for Phase 1 enhancements
Includes user profiles, routines, notifications, and habit tracking
"""

from fastapi import APIRouter, HTTPException, Depends, status, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime, date, timedelta
from app.db.database import get_db
from app.models.models import (
    UserProfile, DailyRoutine, RoutineExecution, Notification,
    DailyChecklist, HabitTracker
)
from app.schemas.schemas import (
    UserProfileCreate, UserProfileUpdate, UserProfileResponse,
    DailyRoutineCreate, DailyRoutineUpdate, DailyRoutineResponse,
    RoutineExecutionResponse, NotificationCreate, NotificationResponse,
    NotificationListResponse, DailyChecklistCreate, DailyChecklistUpdate,
    DailyChecklistResponse, HabitTrackerCreate, HabitTrackerResponse,
    HabitCompletionRequest, ChecklistItem
)

router = APIRouter(prefix="/api/daily-helper", tags=["Daily Helper"])


# ============================================================================
# USER PROFILE ENDPOINTS
# ============================================================================

@router.post("/profile", response_model=UserProfileResponse, status_code=status.HTTP_201_CREATED)
async def create_user_profile(
    profile: UserProfileCreate,
    db: Session = Depends(get_db)
):
    """Create a new user profile"""
    # Check if email already exists
    if profile.email:
        existing = db.query(UserProfile).filter(UserProfile.email == profile.email).first()
        if existing:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Email already registered"
            )

    db_profile = UserProfile(**profile.dict())
    db.add(db_profile)
    db.commit()
    db.refresh(db_profile)
    return db_profile


@router.get("/profile", response_model=UserProfileResponse)
async def get_user_profile(db: Session = Depends(get_db)):
    """Get user profile (current implementation returns first profile)"""
    profile = db.query(UserProfile).first()
    if not profile:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User profile not found"
        )
    return profile


@router.put("/profile", response_model=UserProfileResponse)
async def update_user_profile(
    profile_update: UserProfileUpdate,
    db: Session = Depends(get_db)
):
    """Update user profile"""
    profile = db.query(UserProfile).first()
    if not profile:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User profile not found"
        )

    update_data = profile_update.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(profile, key, value)

    profile.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(profile)
    return profile


@router.delete("/profile", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user_profile(db: Session = Depends(get_db)):
    """Delete user profile"""
    profile = db.query(UserProfile).first()
    if not profile:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User profile not found"
        )
    db.delete(profile)
    db.commit()


# ============================================================================
# DAILY ROUTINE ENDPOINTS
# ============================================================================

@router.post("/routines", response_model=DailyRoutineResponse, status_code=status.HTTP_201_CREATED)
async def create_routine(
    routine: DailyRoutineCreate,
    db: Session = Depends(get_db)
):
    """Create a new daily routine"""
    db_routine = DailyRoutine(**routine.dict())
    db.add(db_routine)
    db.commit()
    db.refresh(db_routine)
    return db_routine


@router.get("/routines", response_model=List[DailyRoutineResponse])
async def list_routines(
    routine_type: Optional[str] = Query(None),
    enabled: Optional[bool] = Query(None),
    db: Session = Depends(get_db)
):
    """List daily routines with optional filters"""
    query = db.query(DailyRoutine)

    if routine_type:
        query = query.filter(DailyRoutine.routine_type == routine_type)
    if enabled is not None:
        query = query.filter(DailyRoutine.enabled == enabled)

    return query.all()


@router.get("/routines/{routine_id}", response_model=DailyRoutineResponse)
async def get_routine(routine_id: int, db: Session = Depends(get_db)):
    """Get a specific routine"""
    routine = db.query(DailyRoutine).filter(DailyRoutine.id == routine_id).first()
    if not routine:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Routine not found"
        )
    return routine


@router.put("/routines/{routine_id}", response_model=DailyRoutineResponse)
async def update_routine(
    routine_id: int,
    routine_update: DailyRoutineUpdate,
    db: Session = Depends(get_db)
):
    """Update a routine"""
    routine = db.query(DailyRoutine).filter(DailyRoutine.id == routine_id).first()
    if not routine:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Routine not found"
        )

    update_data = routine_update.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(routine, key, value)

    routine.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(routine)
    return routine


@router.delete("/routines/{routine_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_routine(routine_id: int, db: Session = Depends(get_db)):
    """Delete a routine"""
    routine = db.query(DailyRoutine).filter(DailyRoutine.id == routine_id).first()
    if not routine:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Routine not found"
        )
    db.delete(routine)
    db.commit()


@router.post("/routines/{routine_id}/execute", response_model=RoutineExecutionResponse, status_code=status.HTTP_201_CREATED)
async def execute_routine(
    routine_id: int,
    db: Session = Depends(get_db)
):
    """Execute a routine (log execution)"""
    routine = db.query(DailyRoutine).filter(DailyRoutine.id == routine_id).first()
    if not routine:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Routine not found"
        )

    # Create execution record
    execution = RoutineExecution(
        routine_id=routine_id,
        completion_status="completed",
        tasks_completed=routine.tasks
    )
    db.add(execution)
    db.commit()
    db.refresh(execution)
    return execution


@router.get("/routines/{routine_id}/executions", response_model=List[RoutineExecutionResponse])
async def get_routine_executions(
    routine_id: int,
    limit: int = Query(10, ge=1, le=100),
    db: Session = Depends(get_db)
):
    """Get execution history for a routine"""
    executions = db.query(RoutineExecution).filter(
        RoutineExecution.routine_id == routine_id
    ).order_by(RoutineExecution.executed_at.desc()).limit(limit).all()
    return executions


# ============================================================================
# NOTIFICATION ENDPOINTS
# ============================================================================

@router.post("/notifications", response_model=NotificationResponse, status_code=status.HTTP_201_CREATED)
async def create_notification(
    notification: NotificationCreate,
    db: Session = Depends(get_db)
):
    """Create a new notification"""
    db_notification = Notification(**notification.dict())
    db.add(db_notification)
    db.commit()
    db.refresh(db_notification)
    return db_notification


@router.get("/notifications", response_model=NotificationListResponse)
async def get_notifications(
    notification_type: Optional[str] = Query(None),
    read: Optional[bool] = Query(None),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    db: Session = Depends(get_db)
):
    """Get notifications with optional filters"""
    query = db.query(Notification)

    if notification_type:
        query = query.filter(Notification.notification_type == notification_type)
    if read is not None:
        query = query.filter(Notification.read == read)

    total = query.count()
    unread = query.filter(Notification.read == False).count()

    notifications = query.order_by(
        Notification.created_at.desc()
    ).limit(limit).offset(offset).all()

    return NotificationListResponse(
        notifications=notifications,
        unread_count=unread,
        total_count=total
    )


@router.get("/notifications/{notification_id}", response_model=NotificationResponse)
async def get_notification(notification_id: int, db: Session = Depends(get_db)):
    """Get a specific notification"""
    notification = db.query(Notification).filter(
        Notification.id == notification_id
    ).first()
    if not notification:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Notification not found"
        )
    return notification


@router.put("/notifications/{notification_id}/read", response_model=NotificationResponse)
async def mark_notification_read(
    notification_id: int,
    db: Session = Depends(get_db)
):
    """Mark notification as read"""
    notification = db.query(Notification).filter(
        Notification.id == notification_id
    ).first()
    if not notification:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Notification not found"
        )

    notification.read = True
    notification.read_at = datetime.utcnow()
    db.commit()
    db.refresh(notification)
    return notification


@router.post("/notifications/mark-all-read")
async def mark_all_notifications_read(db: Session = Depends(get_db)):
    """Mark all notifications as read"""
    db.query(Notification).filter(Notification.read == False).update({
        Notification.read: True,
        Notification.read_at: datetime.utcnow()
    })
    db.commit()
    return {"message": "All notifications marked as read"}


@router.delete("/notifications/{notification_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_notification(notification_id: int, db: Session = Depends(get_db)):
    """Delete a notification"""
    notification = db.query(Notification).filter(
        Notification.id == notification_id
    ).first()
    if not notification:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Notification not found"
        )
    db.delete(notification)
    db.commit()


# ============================================================================
# DAILY CHECKLIST ENDPOINTS
# ============================================================================

@router.post("/checklists", response_model=DailyChecklistResponse, status_code=status.HTTP_201_CREATED)
async def create_checklist(
    checklist: DailyChecklistCreate,
    db: Session = Depends(get_db)
):
    """Create a new daily checklist"""
    db_checklist = DailyChecklist(**checklist.dict())
    db.add(db_checklist)
    db.commit()
    db.refresh(db_checklist)
    return db_checklist


@router.get("/checklists/today", response_model=Optional[DailyChecklistResponse])
async def get_today_checklist(
    checklist_type: Optional[str] = Query(None),
    db: Session = Depends(get_db)
):
    """Get today's checklist"""
    query = db.query(DailyChecklist).filter(
        DailyChecklist.checklist_date == date.today()
    )

    if checklist_type:
        query = query.filter(DailyChecklist.checklist_type == checklist_type)

    return query.first()


@router.get("/checklists", response_model=List[DailyChecklistResponse])
async def list_checklists(
    checklist_type: Optional[str] = Query(None),
    start_date: Optional[str] = Query(None),
    end_date: Optional[str] = Query(None),
    limit: int = Query(30, ge=1, le=365),
    db: Session = Depends(get_db)
):
    """List checklists with optional filters"""
    query = db.query(DailyChecklist)

    if checklist_type:
        query = query.filter(DailyChecklist.checklist_type == checklist_type)

    if start_date:
        try:
            start = datetime.fromisoformat(start_date).date()
            query = query.filter(DailyChecklist.checklist_date >= start)
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid start_date format")

    if end_date:
        try:
            end = datetime.fromisoformat(end_date).date()
            query = query.filter(DailyChecklist.checklist_date <= end)
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid end_date format")

    return query.order_by(DailyChecklist.checklist_date.desc()).limit(limit).all()


@router.get("/checklists/{checklist_id}", response_model=DailyChecklistResponse)
async def get_checklist(checklist_id: int, db: Session = Depends(get_db)):
    """Get a specific checklist"""
    checklist = db.query(DailyChecklist).filter(
        DailyChecklist.id == checklist_id
    ).first()
    if not checklist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Checklist not found"
        )
    return checklist


@router.put("/checklists/{checklist_id}", response_model=DailyChecklistResponse)
async def update_checklist(
    checklist_id: int,
    checklist_update: DailyChecklistUpdate,
    db: Session = Depends(get_db)
):
    """Update a checklist"""
    checklist = db.query(DailyChecklist).filter(
        DailyChecklist.id == checklist_id
    ).first()
    if not checklist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Checklist not found"
        )

    update_data = checklist_update.dict(exclude_unset=True)

    # Calculate completion percentage if items are provided
    if "items" in update_data:
        items = update_data["items"]
        if items:
            completed = sum(1 for item in items if item.get("completed", False))
            completion_pct = (completed / len(items)) * 100
            update_data["completion_percentage"] = completion_pct

    for key, value in update_data.items():
        setattr(checklist, key, value)

    checklist.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(checklist)
    return checklist


@router.put("/checklists/{checklist_id}/items/{item_id}", response_model=DailyChecklistResponse)
async def update_checklist_item(
    checklist_id: int,
    item_id: str,
    completed: bool,
    db: Session = Depends(get_db)
):
    """Update a specific checklist item"""
    checklist = db.query(DailyChecklist).filter(
        DailyChecklist.id == checklist_id
    ).first()
    if not checklist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Checklist not found"
        )

    # Find and update item
    items = checklist.items or []
    for item in items:
        if item.get("id") == item_id:
            item["completed"] = completed
            if completed:
                item["completed_at"] = datetime.utcnow().isoformat()
            break

    # Recalculate completion percentage
    if items:
        completed_count = sum(1 for item in items if item.get("completed", False))
        checklist.completion_percentage = (completed_count / len(items)) * 100

    checklist.items = items
    checklist.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(checklist)
    return checklist


@router.delete("/checklists/{checklist_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_checklist(checklist_id: int, db: Session = Depends(get_db)):
    """Delete a checklist"""
    checklist = db.query(DailyChecklist).filter(
        DailyChecklist.id == checklist_id
    ).first()
    if not checklist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Checklist not found"
        )
    db.delete(checklist)
    db.commit()


# ============================================================================
# HABIT TRACKER ENDPOINTS
# ============================================================================

@router.post("/habits", response_model=HabitTrackerResponse, status_code=status.HTTP_201_CREATED)
async def create_habit(
    habit: HabitTrackerCreate,
    db: Session = Depends(get_db)
):
    """Create a new habit to track"""
    db_habit = HabitTracker(**habit.dict())
    db.add(db_habit)
    db.commit()
    db.refresh(db_habit)
    return db_habit


@router.get("/habits", response_model=List[HabitTrackerResponse])
async def list_habits(
    habit_name: Optional[str] = Query(None),
    db: Session = Depends(get_db)
):
    """List all habits"""
    query = db.query(HabitTracker)

    if habit_name:
        query = query.filter(HabitTracker.habit_name.ilike(f"%{habit_name}%"))

    return query.all()


@router.get("/habits/{habit_id}", response_model=HabitTrackerResponse)
async def get_habit(habit_id: int, db: Session = Depends(get_db)):
    """Get a specific habit"""
    habit = db.query(HabitTracker).filter(HabitTracker.id == habit_id).first()
    if not habit:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Habit not found"
        )
    return habit


@router.post("/habits/{habit_id}/log", response_model=HabitTrackerResponse)
async def log_habit_completion(
    habit_id: int,
    request: HabitCompletionRequest,
    db: Session = Depends(get_db)
):
    """Log habit completion"""
    habit = db.query(HabitTracker).filter(HabitTracker.id == habit_id).first()
    if not habit:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Habit not found"
        )

    completion_date = request.completion_date or date.today().isoformat()
    completion_dates = habit.completion_dates or []

    # Avoid duplicates
    if completion_date not in completion_dates:
        completion_dates.append(completion_date)
        habit.completion_dates = completion_dates
        habit.total_completions = len(completion_dates)

        # Calculate streaks
        sorted_dates = sorted(completion_dates)
        current_streak = 0
        for i in range(len(sorted_dates) - 1, -1, -1):
            current_date = datetime.fromisoformat(sorted_dates[i]).date()
            expected_date = date.today() - timedelta(days=len(sorted_dates) - 1 - i)

            if i == len(sorted_dates) - 1:
                if current_date >= date.today() - timedelta(days=1):
                    current_streak = 1
                else:
                    break
            else:
                next_date = datetime.fromisoformat(sorted_dates[i + 1]).date()
                if next_date - current_date == timedelta(days=1):
                    current_streak += 1
                else:
                    break

        habit.current_streak = current_streak
        habit.longest_streak = max(habit.longest_streak or 0, current_streak)
        habit.updated_at = datetime.utcnow()
        db.commit()
        db.refresh(habit)

    return habit


@router.delete("/habits/{habit_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_habit(habit_id: int, db: Session = Depends(get_db)):
    """Delete a habit"""
    habit = db.query(HabitTracker).filter(HabitTracker.id == habit_id).first()
    if not habit:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Habit not found"
        )
    db.delete(habit)
    db.commit()


# ============================================================================
# SUMMARY ENDPOINTS
# ============================================================================

@router.get("/dashboard")
async def get_dashboard_summary(db: Session = Depends(get_db)):
    """Get daily helper dashboard summary"""
    today = date.today()

    # Get today's checklists
    checklists = db.query(DailyChecklist).filter(
        DailyChecklist.checklist_date == today
    ).all()

    # Get unread notifications
    unread_notifications = db.query(Notification).filter(
        Notification.read == False
    ).count()

    # Get habits
    habits = db.query(HabitTracker).all()
    habit_summary = {
        "total": len(habits),
        "completed_today": sum(
            1 for h in habits
            if h.completion_dates and today.isoformat() in h.completion_dates
        )
    }

    # Get user profile
    profile = db.query(UserProfile).first()

    return {
        "user_profile": profile if profile else None,
        "today_date": today.isoformat(),
        "checklists": checklists,
        "checklists_count": len(checklists),
        "unread_notifications": unread_notifications,
        "habits_summary": habit_summary,
        "pending_routines": db.query(DailyRoutine).filter(
            DailyRoutine.enabled == True
        ).count()
    }
