from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List

from database import get_db
from models.flag import TableFlagDef, TableFlagAssignment
from schemas.flag import FlagDefCreate, FlagDefUpdate, FlagDefOut, FlagAssignmentOut, SetTableFlagsRequest
from routers.deps import get_current_user, require_manager
from models.user import User
from services.sse_bus import broadcast_sync

router = APIRouter()


# ─── Flag definitions (manager only) ─────────────────────────────────────────

@router.get("/defs", response_model=List[FlagDefOut])
def list_flag_defs(
    include_inactive: bool = False,
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    q = db.query(TableFlagDef)
    if not include_inactive:
        q = q.filter(TableFlagDef.is_active == True)
    return q.order_by(TableFlagDef.sort_order, TableFlagDef.id).all()


@router.post("/defs", response_model=FlagDefOut, status_code=status.HTTP_201_CREATED)
def create_flag_def(
    body: FlagDefCreate,
    db: Session = Depends(get_db),
    user: User = Depends(require_manager),
):
    flag = TableFlagDef(**body.model_dump())
    db.add(flag)
    db.commit()
    db.refresh(flag)
    return flag


@router.put("/defs/{flag_id}", response_model=FlagDefOut)
def update_flag_def(
    flag_id: int,
    body: FlagDefUpdate,
    db: Session = Depends(get_db),
    user: User = Depends(require_manager),
):
    flag = db.query(TableFlagDef).filter(TableFlagDef.id == flag_id).first()
    if not flag:
        raise HTTPException(status_code=404, detail="Flag not found")
    for k, v in body.model_dump(exclude_unset=True).items():
        setattr(flag, k, v)
    db.commit()
    db.refresh(flag)
    return flag


@router.patch("/defs/{flag_id}/toggle-active", response_model=FlagDefOut)
def toggle_flag_active(
    flag_id: int,
    db: Session = Depends(get_db),
    user: User = Depends(require_manager),
):
    flag = db.query(TableFlagDef).filter(TableFlagDef.id == flag_id).first()
    if not flag:
        raise HTTPException(status_code=404, detail="Flag not found")
    flag.is_active = not flag.is_active
    db.commit()
    db.refresh(flag)
    return flag


@router.delete("/defs/{flag_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_flag_def(
    flag_id: int,
    db: Session = Depends(get_db),
    user: User = Depends(require_manager),
):
    flag = db.query(TableFlagDef).filter(TableFlagDef.id == flag_id).first()
    if not flag:
        raise HTTPException(status_code=404, detail="Flag not found")
    in_use = db.query(TableFlagAssignment).filter(TableFlagAssignment.flag_id == flag_id).count()
    if in_use:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"Η σήμανση χρησιμοποιείται σε {in_use} τραπέζι{'α' if in_use != 1 else ''}. Αφαιρέστε την πρώτα.",
        )
    db.delete(flag)
    db.commit()


# ─── All assignments (bulk endpoint for manager views) ───────────────────────

@router.get("/assignments", response_model=List[FlagAssignmentOut])
def get_all_assignments(
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """All active flag assignments across all tables (for manager dashboard bulk load)."""
    return db.query(TableFlagAssignment).all()


# ─── Table flag assignments ───────────────────────────────────────────────────

@router.get("/table/{table_id}", response_model=List[FlagAssignmentOut])
def get_table_flags(
    table_id: int,
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    return db.query(TableFlagAssignment).filter(
        TableFlagAssignment.table_id == table_id
    ).all()


@router.put("/table/{table_id}", response_model=List[FlagAssignmentOut])
def set_table_flags(
    table_id: int,
    body: SetTableFlagsRequest,
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """Replace all flags on a table with the given set of flag_ids."""
    # Validate all flag_ids exist and are active
    if body.flag_ids:
        valid = db.query(TableFlagDef).filter(
            TableFlagDef.id.in_(body.flag_ids),
            TableFlagDef.is_active == True,
        ).count()
        if valid != len(body.flag_ids):
            raise HTTPException(status_code=400, detail="One or more flag IDs are invalid")

    # Delete existing assignments for this table
    db.query(TableFlagAssignment).filter(
        TableFlagAssignment.table_id == table_id
    ).delete(synchronize_session=False)

    # Insert new assignments
    for flag_id in body.flag_ids:
        db.add(TableFlagAssignment(
            table_id=table_id,
            flag_id=flag_id,
            assigned_by=user.id,
        ))

    db.commit()
    result = db.query(TableFlagAssignment).filter(
        TableFlagAssignment.table_id == table_id
    ).all()
    broadcast_sync("table_flags_changed", {"table_id": table_id, "flag_ids": body.flag_ids})
    return result


@router.delete("/table/{table_id}/all", status_code=status.HTTP_204_NO_CONTENT)
def clear_table_flags(
    table_id: int,
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    db.query(TableFlagAssignment).filter(
        TableFlagAssignment.table_id == table_id
    ).delete(synchronize_session=False)
    db.commit()
    broadcast_sync("table_flags_changed", {"table_id": table_id, "flag_ids": []})
