"""Groups router — predefined sets of Duniter identities used in decision circles."""

from __future__ import annotations

import uuid

from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import Response
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from app.database import get_db
from app.dependencies.org import get_active_org_id
from app.models.group import Group, GroupMember
from app.schemas.group import GroupCreate, GroupMemberCreate, GroupMemberOut, GroupOut, GroupSummary
from app.services.auth_service import get_current_identity

router = APIRouter()


@router.get("/", response_model=list[GroupSummary])
async def list_groups(
    db: AsyncSession = Depends(get_db),
    org_id: uuid.UUID | None = Depends(get_active_org_id),
) -> list[GroupSummary]:
    """List groups within the active workspace."""
    stmt = select(Group).options(selectinload(Group.members)).order_by(Group.name)
    if org_id is not None:
        stmt = stmt.where(Group.organization_id == org_id)
    else:
        stmt = stmt.where(Group.organization_id.is_(None))
    result = await db.execute(stmt)
    groups = result.scalars().all()
    return [
        GroupSummary(
            id=g.id,
            name=g.name,
            description=g.description,
            organization_id=g.organization_id,
            member_count=len(g.members),
        )
        for g in groups
    ]


@router.post("/", response_model=GroupOut, status_code=201)
async def create_group(
    payload: GroupCreate,
    db: AsyncSession = Depends(get_db),
    _identity=Depends(get_current_identity),
    org_id: uuid.UUID | None = Depends(get_active_org_id),
) -> GroupOut:
    group = Group(name=payload.name, description=payload.description, organization_id=org_id)
    db.add(group)
    await db.commit()
    await db.refresh(group)
    await db.execute(select(Group).where(Group.id == group.id).options(selectinload(Group.members)))
    return GroupOut.model_validate(group)


@router.get("/{group_id}", response_model=GroupOut)
async def get_group(group_id: uuid.UUID, db: AsyncSession = Depends(get_db)) -> GroupOut:
    result = await db.execute(
        select(Group).where(Group.id == group_id).options(selectinload(Group.members))
    )
    group = result.scalar_one_or_none()
    if group is None:
        raise HTTPException(status_code=404, detail="Group not found")
    return GroupOut.model_validate(group)


@router.delete("/{group_id}", status_code=204, response_class=Response, response_model=None)
async def delete_group(
    group_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _identity=Depends(get_current_identity),
) -> None:
    result = await db.execute(select(Group).where(Group.id == group_id))
    group = result.scalar_one_or_none()
    if group is None:
        raise HTTPException(status_code=404, detail="Group not found")
    await db.delete(group)
    await db.commit()


@router.post("/{group_id}/members", response_model=GroupMemberOut, status_code=201)
async def add_member(
    group_id: uuid.UUID,
    payload: GroupMemberCreate,
    db: AsyncSession = Depends(get_db),
    _identity=Depends(get_current_identity),
) -> GroupMemberOut:
    result = await db.execute(select(Group).where(Group.id == group_id))
    if result.scalar_one_or_none() is None:
        raise HTTPException(status_code=404, detail="Group not found")
    member = GroupMember(
        group_id=group_id,
        display_name=payload.display_name,
        identity_id=payload.identity_id,
    )
    db.add(member)
    await db.commit()
    await db.refresh(member)
    return GroupMemberOut.model_validate(member)


@router.delete("/{group_id}/members/{member_id}", status_code=204, response_class=Response, response_model=None)
async def remove_member(
    group_id: uuid.UUID,
    member_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _identity=Depends(get_current_identity),
) -> None:
    result = await db.execute(
        select(GroupMember).where(GroupMember.id == member_id, GroupMember.group_id == group_id)
    )
    member = result.scalar_one_or_none()
    if member is None:
        raise HTTPException(status_code=404, detail="Member not found")
    await db.delete(member)
    await db.commit()
