"""API routes for board-to-repository linking operations."""

from __future__ import annotations

from typing import TYPE_CHECKING
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, status
from sqlmodel import select
from sqlalchemy.exc import IntegrityError

from app.api.deps import (
    get_board_for_actor_read,
    get_board_for_actor_write,
)
from app.core.logging import get_logger
from app.core.time import utcnow
from app.db import crud
from app.db.session import get_session
from app.models.forgejo_repositories import ForgejoRepository
from app.models.board_repository_links import BoardRepositoryLink
from app.schemas.board_repository_links import (
    BoardRepositoryLinkCreate,
    BoardRepositoryLinkDeleteResponse,
    BoardRepositoryLinkRead,
    BoardRepositoryLinkResponse,
)

if TYPE_CHECKING:
    from sqlalchemy.ext.asyncio.session import AsyncSession


router = APIRouter(prefix="/boards/{board_id}/forgejo/repositories", tags=["board-repositories"])
logger = get_logger(__name__)
SESSION_DEP = Depends(get_session)
BOARD_READ_DEP = Depends(get_board_for_actor_read)
BOARD_WRITE_DEP = Depends(get_board_for_actor_write)


@router.get("", response_model=list[BoardRepositoryLinkRead])
async def list_board_repositories(
    board_id: UUID,
    session: AsyncSession = SESSION_DEP,
    board: BoardRepositoryLink = BOARD_READ_DEP,
) -> list[BoardRepositoryLinkRead]:
    """List repositories linked to a board."""
    statement = select(BoardRepositoryLink).where(
        BoardRepositoryLink.board_id == board_id
    )
    links = (await session.exec(statement)).all()
    return [BoardRepositoryLinkRead.model_validate(link) for link in links]


@router.post("", response_model=BoardRepositoryLinkResponse)
async def link_repository_to_board(
    board_id: UUID,
    payload: BoardRepositoryLinkCreate,
    session: AsyncSession = SESSION_DEP,
    board: BoardRepositoryLink = BOARD_WRITE_DEP,
) -> BoardRepositoryLinkResponse:
    """Link a Forgejo repository to a board."""
    # Verify repository belongs to same organization as board
    repository = await crud.get_by_id(session, ForgejoRepository, payload.repository_id)
    if repository is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Repository not found or access denied",
        )
    if repository.organization_id != board.organization_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Repository must belong to the same organization as the board",
        )

    # Create the link
    link = BoardRepositoryLink(
        board_id=board_id,
        repository_id=payload.repository_id,
        organization_id=board.organization_id,
    )
    try:
        await crud.create(session, BoardRepositoryLink, **link.model_dump())
        await session.flush()
        link_read = BoardRepositoryLinkRead.model_validate(link)
        return BoardRepositoryLinkResponse(link=link_read)
    except IntegrityError:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Repository is already linked to this board",
        )


@router.delete("/{repository_id}", response_model=BoardRepositoryLinkDeleteResponse)
async def unlink_repository_from_board(
    board_id: UUID,
    repository_id: UUID,
    session: AsyncSession = SESSION_DEP,
    board: BoardRepositoryLink = BOARD_WRITE_DEP,
) -> BoardRepositoryLinkDeleteResponse:
    """Remove a repository link from a board."""
    statement = select(BoardRepositoryLink).where(
        BoardRepositoryLink.board_id == board_id,
        BoardRepositoryLink.repository_id == repository_id,
    )
    link = (await session.exec(statement)).first()
    if link is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Repository link not found",
        )
    await session.delete(link)
    await session.commit()
    return BoardRepositoryLinkDeleteResponse(
        success=True,
        message="Repository unlinked successfully",
    )
