"""Role management routes."""

from __future__ import annotations

import uuid

from fastapi import APIRouter, Depends, HTTPException, Response, status
from fastapi.responses import JSONResponse
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.audit import log_audit
from app.core.auth import get_redis
from app.core.db import get_db
from app.core.permission_registry import get_permission_registry
from app.core.permissions import invalidate_all_user_permissions
from app.deps import require_permission
from app.models.plugin import Plugin as PluginModel
from app.plugins.registry import get_registry
from app.schemas.role import RoleCreate, RoleUpdate
from app.services.role_service import role_service

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


SYSTEM_PERMISSIONS: list[dict[str, str]] = [
    {"key": "contacts:read", "label": "Contacts: Read", "category": "system"},
    {"key": "contacts:write", "label": "Contacts: Write", "category": "system"},
    {"key": "contacts:delete", "label": "Contacts: Delete", "category": "system"},
    {"key": "users:read", "label": "Users: Read", "category": "system"},
    {"key": "users:write", "label": "Users: Write", "category": "system"},
    {"key": "users:delete", "label": "Users: Delete", "category": "system"},
    {"key": "roles:read", "label": "Roles: Read", "category": "system"},
    {"key": "roles:write", "label": "Roles: Write", "category": "system"},
    {"key": "roles:delete", "label": "Roles: Delete", "category": "system"},
    {"key": "groups:read", "label": "Groups: Read", "category": "system"},
    {"key": "groups:write", "label": "Groups: Write", "category": "system"},
    {"key": "groups:delete", "label": "Groups: Delete", "category": "system"},
    {"key": "audit:read", "label": "Audit Log: Read", "category": "system"},
    {"key": "settings:read", "label": "Settings: Read", "category": "system"},
    {"key": "settings:write", "label": "Settings: Write", "category": "system"},
    {"key": "plugins:read", "label": "Plugins: Read", "category": "system"},
    {"key": "plugins:install", "label": "Plugins: Install", "category": "system"},
    {"key": "plugins:configure", "label": "Plugins: Configure", "category": "system"},
    {"key": "tenants:read", "label": "Tenants: Read", "category": "system"},
    {"key": "tenants:write", "label": "Tenants: Write", "category": "system"},
    {"key": "tenants:delete", "label": "Tenants: Delete", "category": "system"},
    {"key": "notifications:read", "label": "Notifications: Read", "category": "system"},
    {"key": "notifications:write", "label": "Notifications: Write", "category": "system"},
    {"key": "attachments:read", "label": "Attachments: Read", "category": "system"},
    {"key": "attachments:write", "label": "Attachments: Write", "category": "system"},
    {"key": "attachments:delete", "label": "Attachments: Delete", "category": "system"},
    {"key": "workflows:read", "label": "Workflows: Read", "category": "system"},
    {"key": "workflows:write", "label": "Workflows: Write", "category": "system"},
    {"key": "sequences:read", "label": "Sequences: Read", "category": "system"},
    {"key": "sequences:write", "label": "Sequences: Write", "category": "system"},
    {"key": "addresses:read", "label": "Addresses: Read", "category": "system"},
    {"key": "addresses:write", "label": "Addresses: Write", "category": "system"},
    {"key": "addresses:delete", "label": "Addresses: Delete", "category": "system"},
    {"key": "taxes:read", "label": "Taxes: Read", "category": "system"},
    {"key": "taxes:write", "label": "Taxes: Write", "category": "system"},
    {"key": "currencies:read", "label": "Currencies: Read", "category": "system"},
    {"key": "currencies:write", "label": "Currencies: Write", "category": "system"},
    {"key": "import_export:read", "label": "Import/Export: Read", "category": "system"},
    {"key": "import_export:write", "label": "Import/Export: Write", "category": "system"},
]


@router.get("/permissions")
async def list_permissions(
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permission("roles:read")),
):
    """List all available permissions (system + active plugin permissions).

    Returns permissions grouped by category:
    - ``system``: built-in CRM permissions
    - ``plugins``: permissions from active plugin manifests
    """
    registry = get_registry()
    plugin_perms: list[dict[str, str]] = []

    # Fetch active plugin records from DB
    result = await db.execute(
        select(PluginModel).where(PluginModel.active == True)  # noqa: E712
    )
    active_records = {row.name: row for row in result.scalars().all()}

    # Collect permissions from active plugins' manifests
    seen_keys: set[str] = set()
    for name, plugin in registry._plugins.items():
        if name not in active_records:
            continue
        for perm in plugin.manifest.permissions:
            if perm in seen_keys:
                continue
            seen_keys.add(perm)
            plugin_perms.append({
                "key": perm,
                "label": perm.replace("_", " ").replace(":", ": ").title(),
                "category": "plugins",
                "plugin_name": name,
            })

    return {
        "system": SYSTEM_PERMISSIONS,
        "plugins": plugin_perms,
        "all": SYSTEM_PERMISSIONS + plugin_perms,
        "field_definitions": get_permission_registry().get_all_field_definitions(),
    }


@router.get("")
async def list_roles(
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permission("roles:read")),
):
    """List roles for the current tenant."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    roles = await role_service.list_roles(db, tenant_id)
    return {"items": roles}


@router.post("")
async def create_role(
    body: RoleCreate,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permission("roles:write")),
):
    """Create a custom role (admin only)."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    role = await role_service.create_role(
        db,
        tenant_id,
        body.name,
        body.permissions,
        body.denied_permissions,
        body.field_permissions,
    )
    return JSONResponse(
        status_code=status.HTTP_201_CREATED,
        content={
            "id": str(role.id),
            "name": role.name,
            "permissions": role.permissions,
            "denied_permissions": role.denied_permissions,
            "field_permissions": role.field_permissions,
            "permission_version": role.permission_version,
        },
    )


@router.patch("/{role_id}")
async def update_role(
    role_id: str,
    body: RoleUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permission("roles:write")),
):
    """Update a role (admin only)."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    try:
        rid = uuid.UUID(role_id)
    except ValueError:
        raise HTTPException(
            400, detail={"detail": "Invalid role_id", "code": "invalid_id"}
        ) from None

    role = await role_service.update_role(
        db,
        tenant_id,
        rid,
        body.name,
        body.permissions,
        body.denied_permissions,
        body.field_permissions,
    )
    if role is None:
        raise HTTPException(404, detail={"detail": "Role not found", "code": "not_found"})

    # Invalidate permission cache for all users in this tenant
    redis = get_redis()
    await invalidate_all_user_permissions(redis, tenant_id)

    # Audit log
    acting_user_id = uuid.UUID(current_user["user_id"])
    await log_audit(
        db, tenant_id, acting_user_id, "update", "role", rid,
        changes=body.model_dump(exclude_none=True),
    )

    return {
        "id": str(role.id),
        "name": role.name,
        "permissions": role.permissions,
        "denied_permissions": role.denied_permissions,
        "field_permissions": role.field_permissions,
        "permission_version": role.permission_version,
    }


@router.delete("/{role_id}")
async def delete_role(
    role_id: str,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permission("roles:write")),
):
    """Delete a role (admin only)."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    try:
        rid = uuid.UUID(role_id)
    except ValueError:
        raise HTTPException(
            400, detail={"detail": "Invalid role_id", "code": "invalid_id"}
        ) from None

    success = await role_service.delete_role(db, tenant_id, rid)
    if not success:
        raise HTTPException(404, detail={"detail": "Role not found", "code": "not_found"})

    # Invalidate permission cache for all users in this tenant
    redis = get_redis()
    await invalidate_all_user_permissions(redis, tenant_id)

    acting_user_id = uuid.UUID(current_user["user_id"])
    await log_audit(db, tenant_id, acting_user_id, "delete", "role", rid)

    return Response(status_code=status.HTTP_204_NO_CONTENT)
