"""Workspace provisioning seeds.

Defines the canonical workspace catalogue — one entry per job-function
workspace that every tenant should receive — and the role-permission matrix
that backs each workspace.

Called automatically when a new :class:`~simorgh.apps.tenants.models.Tenant`
is created (via ``WorkspacesConfig._connect_tenant_seed_signal``) and also
available as a standalone management command::

    python manage.py seed_workspaces [--tenant <slug>]

All operations are idempotent: re-running the seed is always safe.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from django.db import transaction

if TYPE_CHECKING:
    from simorgh.apps.organizations.models import OrganizationNode
    from simorgh.apps.tenants.models import Tenant

logger = logging.getLogger("simorgh.workspaces.seeds")


# ---------------------------------------------------------------------------
# Workspace + role catalogue
# ---------------------------------------------------------------------------
# Each entry defines:
#   slug       — unique per tenant, stable identifier
#   name       — display name (English; FA label kept as comment)
#   icon       — Tabler icon name used in the UI
#   roles      — list of roles that auto-enroll into this workspace
#                Each role gets created per-tenant with the given permissions.
# ---------------------------------------------------------------------------

WORKSPACE_CATALOG: list[dict] = [
    # ------------------------------------------------------------------
    # Administration
    # Tenant-wide administrative workspace for platform and IAM admins.
    # ------------------------------------------------------------------
    {
        "slug": "administration",
        "name": "Administration",  # مدیریت
        "icon": "TbSettings",
        "roles": [
            {
                "code": "tenant-admin",
                "name": "Tenant Administrator",  # مدیر سیستم
                "description": "Full administrative access within the tenant.",
                "permissions": [
                    # IAM
                    "iam.role.view",
                    "iam.role.manage",
                    # Organizations
                    "organizations.node.view",
                    "organizations.node.manage",
                    # Memberships
                    "memberships.membership.view",
                    "memberships.membership.manage",
                    # Workspaces
                    "workspaces.workspace.view",
                    "workspaces.workspace.manage",
                    "workspaces.member.manage",
                    "workspaces.role_grant.manage",
                    "workspaces.navigation.manage",
                    # DMS — admin can see all
                    "dms.document_type.view",
                    "dms.document_type.manage",
                    "dms.document.view",
                    "dms.document.create",
                    "dms.document.manage",
                    "dms.document.publish",
                    "dms.repository.view",
                    "dms.repository.manage",
                    "dms.folder.view",
                    "dms.folder.manage",
                    # Helpdesk — admin can see all
                    "helpdesk.ticket.view",
                    "helpdesk.ticket.add",
                    "helpdesk.ticket.change",
                    "helpdesk.ticket.assign",
                    "helpdesk.ticket.close",
                    "helpdesk.ticket.reopen",
                    "helpdesk.ticket.merge",
                    "helpdesk.reply.view",
                    "helpdesk.reply.add",
                    "helpdesk.reply.change",
                    "helpdesk.reply.delete",
                    "helpdesk.reply.note",
                    "helpdesk.queue.view",
                    "helpdesk.queue.add",
                    "helpdesk.queue.change",
                    "helpdesk.queue.delete",
                    "helpdesk.category.view",
                    "helpdesk.category.add",
                    "helpdesk.category.change",
                    "helpdesk.category.delete",
                ],
            },
        ],
    },

    # ------------------------------------------------------------------
    # Management
    # Cross-department visibility for directors and department managers.
    # ------------------------------------------------------------------
    {
        "slug": "management",
        "name": "Management",  # مدیریت ارشد
        "icon": "TbBriefcase2",
        "roles": [
            {
                "code": "tenant-manager",
                "name": "Department Manager",  # مدیر بخش
                "description": "Cross-department management and read-only oversight.",
                "permissions": [
                    "iam.role.view",
                    "organizations.node.view",
                    "memberships.membership.view",
                    "workspaces.workspace.view",
                    # DMS — read-only overview
                    "dms.document_type.view",
                    "dms.document.view",
                    "dms.repository.view",
                    "dms.folder.view",
                    # Helpdesk — read-only overview
                    "helpdesk.ticket.view",
                    "helpdesk.reply.view",
                    "helpdesk.queue.view",
                    "helpdesk.category.view",
                ],
            },
        ],
    },

    # ------------------------------------------------------------------
    # Document Management (DMS)
    # Document lifecycle: managers publish, staff create and edit.
    # ------------------------------------------------------------------
    {
        "slug": "document-management",
        "name": "Document Management",  # مدیریت اسناد
        "icon": "TbFiles",
        "roles": [
            {
                "code": "dms-manager",
                "name": "Document Manager",  # مدیر اسناد
                "description": "Full document and repository lifecycle management.",
                "permissions": [
                    "dms.document_type.view",
                    "dms.document_type.manage",
                    "dms.document.view",
                    "dms.document.create",
                    "dms.document.manage",
                    "dms.document.publish",
                    "dms.repository.view",
                    "dms.repository.manage",
                    "dms.folder.view",
                    "dms.folder.manage",
                ],
            },
            {
                "code": "dms-staff",
                "name": "Document Staff",  # کارشناس اسناد
                "description": "Create and upload documents within assigned repositories.",
                "permissions": [
                    "dms.document_type.view",
                    "dms.document.view",
                    "dms.document.create",
                    "dms.repository.view",
                    "dms.folder.view",
                ],
            },
        ],
    },

    # ------------------------------------------------------------------
    # Support Center (Helpdesk)
    # Managers configure queues and SLAs; agents handle tickets.
    # ------------------------------------------------------------------
    {
        "slug": "support-center",
        "name": "Support Center",  # مرکز پشتیبانی
        "icon": "TbHeadset",
        "roles": [
            {
                "code": "helpdesk-manager",
                "name": "Support Manager",  # مدیر پشتیبانی
                "description": "Full helpdesk operations including queues, categories, and SLAs.",
                "permissions": [
                    "helpdesk.ticket.view",
                    "helpdesk.ticket.add",
                    "helpdesk.ticket.change",
                    "helpdesk.ticket.assign",
                    "helpdesk.ticket.close",
                    "helpdesk.ticket.reopen",
                    "helpdesk.ticket.merge",
                    "helpdesk.reply.view",
                    "helpdesk.reply.add",
                    "helpdesk.reply.change",
                    "helpdesk.reply.delete",
                    "helpdesk.reply.note",
                    "helpdesk.queue.view",
                    "helpdesk.queue.add",
                    "helpdesk.queue.change",
                    "helpdesk.queue.delete",
                    "helpdesk.category.view",
                    "helpdesk.category.add",
                    "helpdesk.category.change",
                    "helpdesk.category.delete",
                ],
            },
            {
                "code": "helpdesk-agent",
                "name": "Support Agent",  # کارشناس پشتیبانی
                "description": "Handle tickets, add replies, and resolve support issues.",
                "permissions": [
                    "helpdesk.ticket.view",
                    "helpdesk.ticket.add",
                    "helpdesk.ticket.change",
                    "helpdesk.ticket.assign",
                    "helpdesk.ticket.close",
                    "helpdesk.ticket.reopen",
                    "helpdesk.reply.view",
                    "helpdesk.reply.add",
                    "helpdesk.reply.note",
                    "helpdesk.queue.view",
                    "helpdesk.category.view",
                ],
            },
        ],
    },
]


# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------

def _seed_workspace(
    tenant: Tenant,
    org_node: OrganizationNode,
    spec: dict,
) -> tuple:
    """Get-or-create the workspace described by *spec*.

    Returns ``(workspace, created)`` so callers can log outcome.
    """
    from simorgh.apps.workspaces.models import Workspace, WorkspaceKind  # noqa: PLC0415

    workspace, created = Workspace.objects.get_or_create(
        tenant=tenant,
        slug=spec["slug"],
        defaults={
            "name": spec["name"],
            "kind": WorkspaceKind.INTERNAL,
            "icon": spec.get("icon", ""),
            "is_active": True,
            "organization_node": org_node,
        },
    )
    return workspace, created


def _seed_role(tenant: Tenant, spec: dict) -> tuple:
    """Get-or-create the tenant-scoped role described by *spec*.

    If the role already exists its name/description are **not** overwritten
    so admin edits are preserved.  Only permissions are updated (union, never
    revoked) — missing codenames are silently skipped.
    Returns ``(role, created)``.
    """
    from simorgh.apps.iam.models import Permission, Role  # noqa: PLC0415

    role, created = Role.objects.get_or_create(
        tenant=tenant,
        code=spec["code"],
        defaults={
            "name": spec["name"],
            "description": spec.get("description", ""),
            "is_system": False,
        },
    )

    # Sync permissions: add any new ones, but never remove existing ones.
    perm_codes = spec.get("permissions", [])
    if perm_codes:
        perms = Permission.objects.filter(codename__in=perm_codes)
        if perms.exists():
            role.permissions.add(*perms)

    return role, created


def _seed_access_grant(workspace, role, tenant, org_node) -> tuple:
    """Get-or-create the WorkspaceAccessGrant linking *workspace* ↔ *role*."""
    from simorgh.apps.workspaces.models import WorkspaceAccessGrant  # noqa: PLC0415

    grant, created = WorkspaceAccessGrant.objects.get_or_create(
        workspace=workspace,
        role=role,
        defaults={"tenant": tenant, "organization_node": org_node},
    )
    return grant, created


# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------

@transaction.atomic
def seed_workspaces_for_tenant(tenant: Tenant) -> dict:
    """Idempotently provision canonical workspaces and roles for *tenant*.

    Steps per workspace spec:
    1. Get-or-create the :class:`~simorgh.apps.workspaces.models.Workspace`.
    2. For each role in the spec: get-or-create the tenant-scoped
       :class:`~simorgh.apps.iam.models.Role` and sync its permissions.
    3. Get-or-create the
       :class:`~simorgh.apps.workspaces.models.WorkspaceAccessGrant` (workspace ↔ role).

    Returns a summary dict suitable for logging / management command output.
    Silently returns ``{"status": "skipped"}`` when the tenant has no root
    organisation node yet (the seed can be re-triggered later).
    """
    from simorgh.apps.organizations.models import OrganizationNode  # noqa: PLC0415

    org_node = (
        OrganizationNode.objects.filter(tenant=tenant, parent__isnull=True)
        .order_by("pk")
        .first()
    )
    if org_node is None:
        logger.warning(
            "seed_workspaces: no root org node for tenant %s — skipping",
            getattr(tenant, "slug", tenant.pk),
        )
        return {"status": "skipped", "reason": "no_root_org_node"}

    summary: dict = {
        "status": "ok",
        "tenant": getattr(tenant, "slug", str(tenant.pk)),
        "workspaces": [],
    }

    for ws_spec in WORKSPACE_CATALOG:
        workspace, ws_created = _seed_workspace(tenant, org_node, ws_spec)
        ws_summary = {
            "slug": workspace.slug,
            "created": ws_created,
            "roles": [],
        }

        for role_spec in ws_spec["roles"]:
            role, role_created = _seed_role(tenant, role_spec)
            grant, grant_created = _seed_access_grant(workspace, role, tenant, org_node)
            ws_summary["roles"].append(
                {
                    "code": role.code,
                    "role_created": role_created,
                    "grant_created": grant_created,
                }
            )
            logger.info(
                "seed_workspaces: tenant=%s ws=%s role=%s ws_new=%s role_new=%s grant_new=%s",
                tenant.slug if hasattr(tenant, "slug") else tenant.pk,
                workspace.slug,
                role.code,
                ws_created,
                role_created,
                grant_created,
            )

        summary["workspaces"].append(ws_summary)

    return summary
