﻿from typing import List
from datetime import datetime, timezone, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select

from app.api.deps import get_current_active_user
from app.core.db import get_session
from app.models.models import User, MentorSlot
from app.schemas.auth import MentorPublicResponse, SlotCreate, SlotResponse, BookingConfirmationResponse

router = APIRouter(prefix="/mentors", tags=["mentors"])


def _hydrate_slot(slot: MentorSlot, session: Session) -> SlotResponse:
    """Build a SlotResponse with booked_by_display_name populated."""
    booked_by_display_name = None
    if slot.booked_by_id:
        booker = session.get(User, slot.booked_by_id)
        if booker:
            booked_by_display_name = booker.display_name or booker.username
    return SlotResponse(
        id=slot.id,
        mentor_id=slot.mentor_id,
        start_time=slot.start_time,
        end_time=slot.end_time,
        title=slot.title,
        notes=slot.notes,
        is_booked=slot.is_booked,
        booked_by_id=slot.booked_by_id,
        booked_by_display_name=booked_by_display_name,
    )


@router.get("", response_model=List[MentorPublicResponse])
def list_mentors(session: Session = Depends(get_session)):
    return session.exec(
        select(User).where(User.community_role == "mentor", User.is_active == True)
    ).all()


@router.get("/me/slots", response_model=List[SlotResponse])
def get_my_slots(
    current_user: User = Depends(get_current_active_user),
    session: Session = Depends(get_session),
):
    slots = session.exec(
        select(MentorSlot)
        .where(MentorSlot.mentor_id == current_user.id)
        .order_by(MentorSlot.start_time)
    ).all()
    return [_hydrate_slot(s, session) for s in slots]


@router.post("/me/slots", response_model=List[SlotResponse], status_code=201)
def create_slot(
    payload: SlotCreate,
    current_user: User = Depends(get_current_active_user),
    session: Session = Depends(get_session),
):
    if current_user.community_role != "mentor":
        raise HTTPException(status_code=403, detail="Only mentors can create availability slots")
    if payload.start_time >= payload.end_time:
        raise HTTPException(status_code=400, detail="end_time must be after start_time")
    now = datetime.now(timezone.utc).replace(tzinfo=None)
    if payload.start_time < now:
        raise HTTPException(status_code=400, detail="Slot cannot be in the past")

    recurrence = payload.recurrence or "none"
    count = max(1, payload.recurrence_count or 1)
    delta = timedelta(days=1) if recurrence == "daily" else timedelta(weeks=1)
    duration = payload.end_time - payload.start_time

    created = []
    for i in range(count):
        offset = delta * i if recurrence != "none" else timedelta(0)
        slot = MentorSlot(
            mentor_id=current_user.id,
            start_time=payload.start_time + offset,
            end_time=payload.start_time + offset + duration,
            title=payload.title,
            notes=payload.notes,
        )
        session.add(slot)
    session.flush()

    # Re-query to get IDs
    slots = session.exec(
        select(MentorSlot)
        .where(MentorSlot.mentor_id == current_user.id)
        .order_by(MentorSlot.start_time.desc())
        .limit(count)
    ).all()
    session.commit()
    for s in slots:
        session.refresh(s)
    return [_hydrate_slot(s, session) for s in reversed(slots)]


@router.delete("/me/slots/{slot_id}", status_code=204)
def delete_slot(
    slot_id: int,
    current_user: User = Depends(get_current_active_user),
    session: Session = Depends(get_session),
):
    slot = session.get(MentorSlot, slot_id)
    if not slot or slot.mentor_id != current_user.id:
        raise HTTPException(status_code=404, detail="Slot not found")
    if slot.is_booked:
        raise HTTPException(status_code=409, detail="Cannot delete a booked slot")
    session.delete(slot)
    session.commit()


@router.get("/{user_id}", response_model=MentorPublicResponse)
def get_mentor(user_id: int, session: Session = Depends(get_session)):
    user = session.get(User, user_id)
    if not user or user.community_role != "mentor":
        raise HTTPException(status_code=404, detail="Mentor not found")
    return user


@router.get("/{user_id}/slots", response_model=List[SlotResponse])
def get_mentor_slots(user_id: int, session: Session = Depends(get_session)):
    user = session.get(User, user_id)
    if not user or user.community_role != "mentor":
        raise HTTPException(status_code=404, detail="Mentor not found")
    slots = session.exec(
        select(MentorSlot)
        .where(MentorSlot.mentor_id == user_id, MentorSlot.is_booked == False)
        .order_by(MentorSlot.start_time)
    ).all()
    return [_hydrate_slot(s, session) for s in slots]


@router.post("/{user_id}/slots/{slot_id}/book", response_model=BookingConfirmationResponse)
def book_slot(
    user_id: int,
    slot_id: int,
    current_user: User = Depends(get_current_active_user),
    session: Session = Depends(get_session),
):
    slot = session.get(MentorSlot, slot_id)
    if not slot or slot.mentor_id != user_id:
        raise HTTPException(status_code=404, detail="Slot not found")
    if slot.is_booked:
        raise HTTPException(status_code=409, detail="This slot has already been booked")
    if slot.mentor_id == current_user.id:
        raise HTTPException(status_code=400, detail="You cannot book your own slot")
    slot.is_booked = True
    slot.booked_by_id = current_user.id
    session.add(slot)
    session.commit()
    session.refresh(slot)

    mentor = session.get(User, user_id)
    return BookingConfirmationResponse(
        id=slot.id,
        mentor_id=slot.mentor_id,
        start_time=slot.start_time,
        end_time=slot.end_time,
        title=slot.title,
        notes=slot.notes,
        is_booked=slot.is_booked,
        booked_by_id=slot.booked_by_id,
        booked_by_display_name=current_user.display_name or current_user.username,
        mentor_email=mentor.email if mentor else None,
        mentor_display_name=mentor.display_name or mentor.username if mentor else None,
        mentee_email=current_user.email,
    )
