from typing import List

from app.auth import require_auth
from app.database import get_session
from app.models import (
    Folder,
    FolderCreate,
    FolderTreeNode,
    FolderTreeResponse,
    FolderUpdate,
    Note,
    NoteRead,
    User,
)
from fastapi import APIRouter, Depends, HTTPException  # type: ignore
from sqlalchemy.orm import selectinload
from sqlmodel import Session, select  # type: ignore

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


def build_folder_tree_node(folder: Folder) -> FolderTreeNode:
    """Recursively build a folder tree node with notes and children"""
    return FolderTreeNode(
        id=folder.id,  # pyright: ignore[reportArgumentType]
        name=folder.name,
        notes=[NoteRead.model_validate(note) for note in folder.notes],
        children=[build_folder_tree_node(child) for child in folder.children],
    )


@router.get("/tree", response_model=FolderTreeResponse)
def get_folder_tree(
    current_user: User = Depends(require_auth), session: Session = Depends(get_session)
):
    """Get complete folder tree with notes"""

    top_level_folders = session.exec(
        select(Folder)
        .options(selectinload(Folder.notes).selectinload(Note.tags))
        .where(Folder.parent_id == None)
        .where(Folder.user_id == current_user.id)
    ).all()

    orphaned_notes = session.exec(
        select(Note)
        .options(selectinload(Note.tags))
        .where(Note.folder_id == None)
        .where(Note.user_id == current_user.id)
    ).all()

    tree = [build_folder_tree_node(folder) for folder in top_level_folders]

    return FolderTreeResponse(
        folders=tree,
        orphaned_notes=[NoteRead.model_validate(note) for note in orphaned_notes],
    )


@router.get("/", response_model=List[Folder])
def list_folders(session: Session = Depends(get_session)):
    """Get flat list of all folders"""
    folders = session.exec(select(Folder)).all()
    return folders


@router.post("/", response_model=Folder)
def create_folder(
    folder: FolderCreate,
    current_user: User = Depends(require_auth),
    session: Session = Depends(get_session),
):
    """Create a new folder"""
    folder_data = folder.model_dump()
    folder_data["user_id"] = current_user.id
    db_folder = Folder.model_validate(folder_data)
    session.add(db_folder)
    session.commit()
    session.refresh(db_folder)
    return db_folder


@router.delete("/{folder_id}")
def delete_folder(folder_id: int, session: Session = Depends(get_session)):
    """Delete a folder"""
    folder = session.get(Folder, folder_id)
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")

    session.delete(folder)
    session.commit()
    return {"message": "Folder deleted"}


@router.patch("/{folder_id}")
def update_folder(
    folder_id: int, folder_update: FolderUpdate, session: Session = Depends(get_session)
):
    """Update a folder"""
    folder = session.get(Folder, folder_id)
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")

    update_data = folder_update.model_dump(exclude_unset=True)

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

    session.add(folder)
    session.commit()

    session.refresh(folder)

    return folder
