"""
Groups Router
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from pydantic import BaseModel
from datetime import datetime

from app.database import get_db
from app.models.user import User
from app.models.group import Group, user_groups
from app.models.setting import Setting
from app.auth.dependencies import get_current_user, RequireAdmin

router = APIRouter(prefix="/api/v1/groups", tags=["Groups"])

# --- Schemas ---

class GroupCreate(BaseModel):
    name: str
    description: Optional[str] = None
    user_ids: List[int] = []

class GroupUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    user_ids: Optional[List[int]] = None

class GroupResponse(BaseModel):
    id: int
    name: str
    description: Optional[str]
    created_at: datetime
    member_count: int = 0
    members: List[dict] = [] # Include simplified user info

    class Config:
        from_attributes = True

# --- Endpoints ---

@router.get("", response_model=List[GroupResponse])
async def list_groups(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
    groups = db.query(Group).all()
    results = []
    for group in groups:
        # Fetch members manually or via relationship
        members = [{"id": u.id, "username": u.username} for u in group.users]
        results.append({
            "id": group.id,
            "name": group.name,
            "description": group.description,
            "created_at": group.created_at,
            "member_count": len(group.users),
            "members": members
        })
    return results

@router.post("", response_model=GroupResponse)
async def create_group(
    group_in: GroupCreate, 
    db: Session = Depends(get_db), 
    current_user: User = Depends(RequireAdmin)
):
    existing = db.query(Group).filter(Group.name == group_in.name).first()
    if existing:
        raise HTTPException(status_code=400, detail="Group with this name already exists")

    group = Group(
        name=group_in.name,
        description=group_in.description
    )
    db.add(group)
    db.flush() # Get ID

    # Add users
    if group_in.user_ids:
        users = db.query(User).filter(User.id.in_(group_in.user_ids)).all()
        group.users = users

    db.commit()
    db.refresh(group)
    
    members = [{"id": u.id, "username": u.username} for u in group.users]
    return {
        "id": group.id,
        "name": group.name,
        "description": group.description,
        "created_at": group.created_at,
        "member_count": len(group.users),
        "members": members
    }

@router.put("/{group_id}", response_model=GroupResponse)
async def update_group(
    group_id: int, 
    group_in: GroupUpdate, 
    db: Session = Depends(get_db), 
    current_user: User = Depends(RequireAdmin)
):
    group = db.query(Group).filter(Group.id == group_id).first()
    if not group:
        raise HTTPException(status_code=404, detail="Group not found")

    if group_in.name:
        existing = db.query(Group).filter(Group.name == group_in.name, Group.id != group_id).first()
        if existing:
            raise HTTPException(status_code=400, detail="Group name already in use")
        group.name = group_in.name
    
    if group_in.description is not None:
        group.description = group_in.description

    if group_in.user_ids is not None:
        users = db.query(User).filter(User.id.in_(group_in.user_ids)).all()
        group.users = users

    db.commit()
    db.refresh(group)
    
    members = [{"id": u.id, "username": u.username} for u in group.users]
    return {
        "id": group.id,
        "name": group.name,
        "description": group.description,
        "created_at": group.created_at,
        "member_count": len(group.users),
        "members": members
    }

@router.delete("/{group_id}")
async def delete_group(
    group_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(RequireAdmin)
):
    group = db.query(Group).filter(Group.id == group_id).first()
    if not group:
        raise HTTPException(status_code=404, detail="Group not found")

    # Clear M2M relationships first (user_groups and asset_groups tables)
    group.users = []
    group.assets = []
    db.flush()

    # Clear FK assignments in vulnerabilities
    from app.models.vulnerability import Vulnerability
    db.query(Vulnerability).filter(Vulnerability.assigned_group_id == group_id).update({"assigned_group_id": None})

    db.delete(group)
    db.commit()
    return {"message": "Group deleted successfully"}

# --- Settings ---

@router.get("/default", response_model=Optional[int])
async def get_default_group(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
    setting = db.query(Setting).filter(Setting.key == "default_group_id").first()
    if setting and setting.value:
        return int(setting.value)
    return None

@router.post("/default")
async def set_default_group(
    group_id: Optional[int] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(RequireAdmin)
):
    # If group_id is provided, validate the group exists
    if group_id is not None:
        group = db.query(Group).filter(Group.id == group_id).first()
        if not group:
            raise HTTPException(status_code=404, detail="Group not found")

    setting = db.query(Setting).filter(Setting.key == "default_group_id").first()

    if group_id is None:
        # Clear the default group
        if setting:
            db.delete(setting)
            db.commit()
        return {"message": "Default group cleared"}

    if not setting:
        setting = Setting(key="default_group_id", value=str(group_id), description="Default group for new assets")
        db.add(setting)
    else:
        setting.value = str(group_id)

    db.commit()
    return group_id
