"""Dashboard widget configuration service.

Provides async functions for loading and persisting per-user and
tenant-default dashboard widget layouts.
"""
import logging
import uuid
from datetime import datetime

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.domains.admin.models import DashboardConfig

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Widget type literals
# ---------------------------------------------------------------------------

WIDGET_TYPES = (
    "ProductionStats",
    "QueueStatus",
    "RecentRenders",
    "CostOverview",
    "WorkerStatus",
    "KPISummary",
    "OrderThroughput",
    "RevenueChart",
    "ItemStatus",
    "ProcessingTimes",
    "RenderTimeByOutputType",
    "OutputTypeUsage",
    "TopProducts",
    "OrdersByUser",
    "RenderBackendStats",
)

# Default layouts per role
_DEFAULT_ADMIN_WIDGETS: list[dict] = [
    {"widget_type": "KPISummary",     "position": {"col": 0, "row": 0, "w": 1, "h": 1}},
    {"widget_type": "QueueStatus",    "position": {"col": 1, "row": 0, "w": 1, "h": 1}},
    {"widget_type": "WorkerStatus",   "position": {"col": 2, "row": 0, "w": 1, "h": 1}},
    {"widget_type": "OrderThroughput","position": {"col": 0, "row": 1, "w": 2, "h": 1}},
    {"widget_type": "ItemStatus",     "position": {"col": 2, "row": 1, "w": 1, "h": 1}},
    {"widget_type": "RevenueChart",   "position": {"col": 0, "row": 2, "w": 2, "h": 1}},
    {"widget_type": "ProcessingTimes","position": {"col": 2, "row": 2, "w": 1, "h": 1}},
]

_DEFAULT_CLIENT_WIDGETS: list[dict] = [
    {"widget_type": "RecentRenders",   "position": {"col": 0, "row": 0, "w": 2, "h": 1}},
    {"widget_type": "ProductionStats", "position": {"col": 2, "row": 0, "w": 1, "h": 1}},
]


def get_default_widgets_for_role(role: str) -> list[dict]:
    """Return systemwide default widget layout for a given role.

    admin / project_manager: KPI + analytics defaults.
    client: RecentRenders + ProductionStats only.
    """
    if role in ("admin", "project_manager"):
        return [w.copy() for w in _DEFAULT_ADMIN_WIDGETS]
    return [w.copy() for w in _DEFAULT_CLIENT_WIDGETS]


async def get_user_dashboard_config(
    db: AsyncSession,
    user_id: uuid.UUID,
    tenant_id: uuid.UUID | None,
    role: str,
) -> list[dict]:
    """Load widget config with fallback cascade.

    1. User-specific config (user_id match).
    2. Tenant-default config (is_tenant_default=True for the tenant).
    3. System default based on role.
    """
    # 1. User-specific
    result = await db.execute(
        select(DashboardConfig).where(DashboardConfig.user_id == user_id)
    )
    config = result.scalar_one_or_none()
    if config is not None:
        return list(config.widgets) if config.widgets else []

    # 2. Tenant default
    if tenant_id is not None:
        result = await db.execute(
            select(DashboardConfig).where(
                DashboardConfig.tenant_id == tenant_id,
                DashboardConfig.is_tenant_default.is_(True),
            )
        )
        tenant_config = result.scalar_one_or_none()
        if tenant_config is not None:
            return list(tenant_config.widgets) if tenant_config.widgets else []

    # 3. System default
    return get_default_widgets_for_role(role)


async def upsert_user_dashboard_config(
    db: AsyncSession,
    user_id: uuid.UUID,
    tenant_id: uuid.UUID | None,
    widgets: list[dict],
) -> DashboardConfig:
    """Save or update the user-specific widget config."""
    result = await db.execute(
        select(DashboardConfig).where(DashboardConfig.user_id == user_id)
    )
    config = result.scalar_one_or_none()

    if config is None:
        config = DashboardConfig(
            user_id=user_id,
            tenant_id=tenant_id,
            widgets=widgets,
            is_tenant_default=False,
        )
        db.add(config)
    else:
        config.widgets = widgets
        config.updated_at = datetime.utcnow()

    await db.commit()
    await db.refresh(config)
    return config


async def upsert_tenant_default(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    widgets: list[dict],
) -> DashboardConfig:
    """Set the tenant-default widget config (admin only)."""
    result = await db.execute(
        select(DashboardConfig).where(
            DashboardConfig.tenant_id == tenant_id,
            DashboardConfig.is_tenant_default.is_(True),
        )
    )
    config = result.scalar_one_or_none()

    if config is None:
        config = DashboardConfig(
            tenant_id=tenant_id,
            user_id=None,
            widgets=widgets,
            is_tenant_default=True,
        )
        db.add(config)
    else:
        config.widgets = widgets
        config.updated_at = datetime.utcnow()

    await db.commit()
    await db.refresh(config)
    return config
