"""
Master panel staff RBAC (additive; is_master super-users keep full access).

Staff accounts: has_master_panel=1 + per-user permissions in user_master_permissions.
Customer business admins never receive master panel access.
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional

# Permission catalog grouped for UI presets.
MASTER_PERMISSION_GROUPS: List[Dict[str, Any]] = [
    {
        "label": "Panel access",
        "permissions": [
            {"code": "master.panel.access", "label": "Access master panel"},
        ],
    },
    {
        "label": "Businesses",
        "permissions": [
            {"code": "master.businesses.view", "label": "View businesses overview"},
            {"code": "master.businesses.manage", "label": "Manage BID (logs, status, retries)"},
            {"code": "master.businesses.onboard", "label": "Onboard / create businesses"},
            {"code": "master.businesses.delete", "label": "Delete businesses"},
        ],
    },
    {
        "label": "Support",
        "permissions": [
            {"code": "master.support.view", "label": "View all support tickets"},
            {"code": "master.support.reply", "label": "Reply to tickets"},
            {"code": "master.support.resolve", "label": "Resolve / update ticket status"},
            {"code": "master.support.approve_features", "label": "Approve feature-enable requests"},
        ],
    },
    {
        "label": "Usage & billing",
        "permissions": [
            {"code": "master.usage.view", "label": "View usage dashboard"},
            {"code": "master.usage.allocate", "label": "Allocate minutes / change limits"},
        ],
    },
    {
        "label": "STT & pipeline",
        "permissions": [
            {"code": "master.stt.view", "label": "View STT pipeline & status"},
            {"code": "master.stt.manage", "label": "Configure / start STT jobs"},
            {"code": "master.stt.keys", "label": "Update API keys (sensitive)"},
        ],
    },
    {
        "label": "Configuration",
        "permissions": [
            {"code": "master.defaults.view", "label": "View default parameters"},
            {"code": "master.defaults.edit", "label": "Edit default parameters"},
            {"code": "master.webhooks.view", "label": "View webhook ingest log"},
            {"code": "master.audit.view", "label": "View audit / activity log"},
        ],
    },
    {
        "label": "User administration",
        "permissions": [
            {"code": "master.users.view", "label": "View HQ / admin users"},
            {"code": "master.users.manage", "label": "Create users & assign BIDs"},
            {"code": "master.staff.manage", "label": "Manage staff permissions"},
        ],
    },
]

MASTER_PERMISSION_CODES = {
    item["code"]
    for group in MASTER_PERMISSION_GROUPS
    for item in group.get("permissions") or []
}

STAFF_TEAM_PRESETS: Dict[str, List[str]] = {
    "developer": [
        "master.panel.access",
        "master.businesses.view",
        "master.businesses.manage",
        "master.stt.view",
        "master.stt.manage",
        "master.webhooks.view",
        "master.audit.view",
        "master.defaults.view",
        "master.support.view",
        "master.support.reply",
    ],
    "support": [
        "master.panel.access",
        "master.businesses.view",
        "master.support.view",
        "master.support.reply",
        "master.support.resolve",
        "master.support.approve_features",
    ],
    "onboarding": [
        "master.panel.access",
        "master.businesses.view",
        "master.businesses.onboard",
        "master.defaults.view",
        "master.defaults.edit",
        "master.usage.view",
    ],
}

STAFF_TEAMS = ("developer", "support", "onboarding", "custom")


def _truthy(value: Any) -> bool:
    return value is True or value == 1 or str(value).strip() == "1"


def is_super_master(user: Optional[Dict[str, Any]]) -> bool:
    return _truthy((user or {}).get("is_master"))


def master_permissions_list(user: Optional[Dict[str, Any]]) -> List[str]:
    if not user:
        return []
    if is_super_master(user):
        return ["*"]
    perms = user.get("master_permissions") or []
    return sorted({str(p).strip() for p in perms if str(p).strip()})


def has_master_panel_flag(user: Optional[Dict[str, Any]]) -> bool:
    if is_super_master(user):
        return True
    return _truthy((user or {}).get("has_master_panel"))


def has_master_permission(user: Optional[Dict[str, Any]], permission: str) -> bool:
    if is_super_master(user):
        return True
    if not has_master_panel_flag(user):
        return False
    code = str(permission or "").strip()
    if not code:
        return False
    perms = master_permissions_list(user)
    if "*" in perms:
        return True
    return code in perms


def can_access_master_panel(user: Optional[Dict[str, Any]]) -> bool:
    return has_master_permission(user, "master.panel.access")


def can_act_as_master_for_support(user: Optional[Dict[str, Any]]) -> bool:
    """Used where legacy code checked is_master for support inbox actions."""
    if is_super_master(user):
        return True
    return has_master_permission(user, "master.support.view")


def staff_team_value(user: Optional[Dict[str, Any]]) -> str:
    return str((user or {}).get("staff_team") or "").strip().lower()


def can_assign_support_tickets(user: Optional[Dict[str, Any]]) -> bool:
    """Only support staff (or super master) may assign tickets to developers."""
    if is_super_master(user):
        return True
    if staff_team_value(user) != "support":
        return False
    return has_master_permission(user, "master.support.resolve")


def _ticket_assignee_user_id(ticket: Optional[Dict[str, Any]]) -> Optional[int]:
    raw = (ticket or {}).get("assigned_to_user_id")
    try:
        return int(raw) if raw is not None else None
    except (TypeError, ValueError):
        return None


def _staff_user_id(user: Optional[Dict[str, Any]]) -> Optional[int]:
    raw = (user or {}).get("id")
    try:
        return int(raw) if raw is not None else None
    except (TypeError, ValueError):
        return None


def can_update_assigned_ticket_status(
    user: Optional[Dict[str, Any]],
    ticket: Optional[Dict[str, Any]] = None,
) -> bool:
    """Developers may update status on tickets assigned to them; super master on any ticket."""
    if is_super_master(user):
        return True
    if staff_team_value(user) != "developer":
        return False
    if not has_master_permission(user, "master.support.reply"):
        return False
    if not ticket:
        return False
    assignee_id = _ticket_assignee_user_id(ticket)
    user_id = _staff_user_id(user)
    return assignee_id is not None and user_id is not None and assignee_id == user_id


def can_manage_support_email(user: Optional[Dict[str, Any]]) -> bool:
    if is_super_master(user):
        return True
    if staff_team_value(user) != "support":
        return False
    return has_master_permission(user, "master.support.resolve")


def can_approve_support_features(user: Optional[Dict[str, Any]]) -> bool:
    if is_super_master(user):
        return True
    if staff_team_value(user) != "support":
        return False
    return has_master_permission(user, "master.support.approve_features")


def can_resolve_support_tickets(user: Optional[Dict[str, Any]]) -> bool:
    """Legacy alias — support no longer resolves tickets; developers do on assigned tickets."""
    return can_update_assigned_ticket_status(user) or can_manage_support_email(user)


def require_can_assign_support_tickets(user: Optional[Dict[str, Any]]) -> None:
    from fastapi import HTTPException

    if can_assign_support_tickets(user):
        return
    raise HTTPException(status_code=403, detail="Only support staff can assign tickets")


def require_can_resolve_support_tickets(user: Optional[Dict[str, Any]]) -> None:
    require_can_manage_support_email(user)


def require_can_manage_support_email(user: Optional[Dict[str, Any]]) -> None:
    from fastapi import HTTPException

    if can_manage_support_email(user):
        return
    raise HTTPException(status_code=403, detail="Only support staff can manage support email settings")


def require_can_update_assigned_ticket_status(
    user: Optional[Dict[str, Any]],
    ticket: Optional[Dict[str, Any]] = None,
) -> None:
    from fastapi import HTTPException

    if can_update_assigned_ticket_status(user, ticket):
        return
    raise HTTPException(
        status_code=403,
        detail="Only the assigned developer (or super master) can update this ticket status",
    )


def require_master_permission(user: Optional[Dict[str, Any]], permission: str) -> None:
    from fastapi import HTTPException

    if has_master_permission(user, permission):
        return
    raise HTTPException(status_code=403, detail="Master panel permission denied")


def require_master_panel(user: Optional[Dict[str, Any]]) -> None:
    require_master_permission(user, "master.panel.access")


def require_master_access(user: Optional[Dict[str, Any]], permission: Optional[str] = None) -> None:
    """Backward-compatible gate: super master always passes; staff need permission."""
    if permission:
        require_master_permission(user, permission)
    else:
        require_master_panel(user)


def default_landing_path(user: Optional[Dict[str, Any]]) -> str:
    if is_super_master(user):
        return "/pca-master"
    ordered = [
        ("master.businesses.view", "/pca-master"),
        ("master.support.view", "/pca-master/support"),
        ("master.businesses.onboard", "/pca-master/onboarding"),
        ("master.usage.view", "/pca-master/usage"),
        ("master.stt.view", "/pca-master/stt"),
        ("master.defaults.view", "/pca-master/default-parameters"),
        ("master.webhooks.view", "/pca-master/webhook-ingest-log"),
        ("master.audit.view", "/pca-master/audit-trail"),
        ("master.users.view", "/pca-master/hq-users"),
        ("master.staff.manage", "/pca-master/staff-access"),
    ]
    for perm, path in ordered:
        if has_master_permission(user, perm):
            return path
    return "/pca-master"


def permission_catalog() -> Dict[str, Any]:
    return {
        "groups": MASTER_PERMISSION_GROUPS,
        "presets": STAFF_TEAM_PRESETS,
        "teams": list(STAFF_TEAMS),
    }
