"""
Tenant provisioning service for ModuleDesk.

Handles creation of new tenant schemas, running their initial Alembic
migrations, and seeding default data. Called during onboarding after
a new Organization record is created in the public schema.
"""

from __future__ import annotations

import logging
import re

from sqlalchemy import text

from ..db import engine, session_scope
from ..public_models import Organization

logger = logging.getLogger(__name__)

_SAFE_SCHEMA_RE = re.compile(r'^tenant_[a-z0-9_]+$')


def make_schema_name(slug: str) -> str:
    """Derive a safe PostgreSQL schema name from an org slug."""
    safe = re.sub(r'[^a-z0-9]', '_', slug.lower())
    return f"tenant_{safe}"


def provision_tenant(org: Organization) -> None:
    """
    Set up a new tenant's PostgreSQL schema and run all migrations.

    Steps:
      1. CREATE SCHEMA IF NOT EXISTS <schema_name>
      2. Run Alembic tenant migrations against that schema
      3. Seed AppSettings defaults

    This is called synchronously during onboarding (after the org record
    is committed to public.organizations). It is idempotent — safe to
    call again if the schema already exists.
    """
    schema = org.schema_name
    if not _SAFE_SCHEMA_RE.match(schema):
        raise ValueError(f"Unsafe schema name rejected: {schema!r}")

    logger.info("Provisioning tenant schema: %s", schema)

    # Step 1: Create the schema
    with engine.connect() as conn:
        conn.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema}"))
        conn.commit()

    # Step 2: Run Alembic migrations for this schema
    _run_tenant_migrations(schema)

    # Step 3: Seed default AppSettings
    _seed_app_settings(schema)

    logger.info("Tenant schema %s provisioned successfully", schema)


def _run_tenant_migrations(schema: str) -> None:
    """Run Alembic 'upgrade head' for a specific tenant schema."""
    from supporthub.migrations.env import run_migrations_online
    run_migrations_online(schema=schema)


def _seed_app_settings(schema: str) -> None:
    """Insert default AppSettings rows for a new tenant."""
    from ..models import AppSettings
    defaults = {
        "reply_signature": "",
        "auto_close_days": "0",
        "supported_languages": "en",
        "ai_enabled": "true",
    }
    with session_scope(schema=schema) as session:
        for key, value in defaults.items():
            existing = session.get(AppSettings, key)
            if existing is None:
                session.add(AppSettings(key=key, value=value))
