"""Isolated per-tenant data storage with user profiles, permissions, and settings."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_db_tenant.ipynb.

# %% auto #0
__all__ = ['logger', 'get_or_create_tenant_db', 'TenantUser', 'TenantPermission', 'TenantSettings', 'init_tenant_core_schema']

# %% ../nbs/01_db_tenant.ipynb #ef523bd9
from fastsql import *
from fastcore.utils import *
from .db_host import timestamp, gen_id
import urllib.parse
import os
import logging

# Module-level logger - configured by app via configure_logging()
logger = logging.getLogger(__name__)

# %% ../nbs/01_db_tenant.ipynb #45847eb4
def get_or_create_tenant_db(tenant_id: str, tenant_name: str = None):
    """Get or create a tenant database connection by tenant ID.
    
    ⚠️ IMPORTANT: Caller is responsible for closing the returned Database connection
    by calling `db.conn.close()` and `db.engine.dispose()` when done.
    """
    from sqlalchemy import text
    
    # Connect to host - read from environment
    DB_TYPE = os.getenv("DB_TYPE", "POSTGRESQL")
    DB_USER = os.getenv("DB_USER", "postgres")
    DB_PASS = os.getenv("DB_PASS", "")
    DB_HOST = os.getenv("DB_HOST", "localhost")
    DB_PORT = os.getenv("DB_PORT", "5432")
    DB_NAME = os.getenv("DB_NAME", "app_host")  # Host database name
    
    # Build host database connection
    if DB_TYPE == "POSTGRESQL":
        if not DB_PASS:
            raise ValueError("DB_PASS is required for PostgreSQL")
        encoded_pass = urllib.parse.quote_plus(DB_PASS)
        host_url = f"postgresql://{DB_USER}:{encoded_pass}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
    else:
        host_url = f"sqlite:///{DB_NAME}.db"
    
    # Use try/finally to ensure host_db connection is always closed
    host_db = Database(host_url)
    try:
        # Check if tenant registered
        class TenantCatalog:
            id: str; name: str; db_url: str
            is_active: bool = True; plan_tier: str = "free"; created_at: str
        
        tenant_catalogs = host_db.create(TenantCatalog, name="core_tenants", pk='id')
        host_db.conn.rollback()
        all_tenants = tenant_catalogs()
        existing = [t for t in all_tenants if t.id == tenant_id]
        
        # Build tenant database connection
        # PostgreSQL databases cannot start with numbers, so prefix with 't_'
        if DB_TYPE == "POSTGRESQL":
            tenant_db_name = f"t_{tenant_id}_db"
            tenant_url = f"postgresql://{DB_USER}:{encoded_pass}@{DB_HOST}:{DB_PORT}/{tenant_db_name}"
        else:
            tenant_db_name = f"{tenant_id}_db"
            tenant_url = f"sqlite:///{tenant_db_name}.db"
        
        if not existing:
            print(f"⚡ Creating new tenant: {tenant_id}")
            
            # Create physical database (PostgreSQL only)
            if DB_TYPE == "POSTGRESQL":
                with host_db.engine.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
                    try:
                        conn.execute(text(f"CREATE DATABASE {tenant_db_name}"))
                        print(f"   ✅ Database created: {tenant_db_name}")
                    except Exception as e:
                        if "already exists" not in str(e):
                            raise
            
            # Register in host
            new_tenant = TenantCatalog(
                id=tenant_id,
                name=tenant_name or tenant_id,
                db_url=tenant_url,
                created_at=timestamp()
            )
            tenant_catalogs.insert(new_tenant)
            host_db.conn.commit()
            print(f"   ✅ Registered in host DB")
        else:
            print(f"ℹ️  Tenant exists: {existing[0].name}")
            tenant_url = existing[0].db_url
        
        return Database(tenant_url)
    finally:
        # Always close the internal host_db connection to prevent leaks
        try:
            host_db.conn.close()
            host_db.engine.dispose()
        except Exception:
            pass  # Ignore cleanup errors

# %% ../nbs/01_db_tenant.ipynb #f9da900f
class TenantUser:
    """Local user profile linked to GlobalUser in host database."""
    id: str              # MUST match GlobalUser.id from host DB
    display_name: str    # e.g. "John Doe"
    local_role: str      # 'admin', 'editor', 'viewer'
    preferences: str = None  # JSON settings
    last_active: str = None
    created_at: str

class TenantPermission:
    """Fine-grained resource permission for a tenant user."""
    id: str
    user_id: str         # Links to TenantUser.id
    resource: str        # 'transactions', 'budgets', 'reports'
    action: str          # 'view', 'edit', 'delete'
    granted: bool = True
    created_at: str

class TenantSettings:
    """Tenant-wide configuration and feature flags."""
    id: str = "default"
    tenant_name: str
    timezone: str = "UTC"
    currency: str = "USD"
    feature_flags: str = None  # JSON
    updated_at: str

# %% ../nbs/01_db_tenant.ipynb #ac425da6
def init_tenant_core_schema(tenant_db: Database):
    """Create all core tenant tables and return table accessors."""
    tenant_users = tenant_db.create(TenantUser, name="core_tenant_users", pk='id')
    permissions = tenant_db.create(TenantPermission, name="core_permissions", pk='id')
    settings = tenant_db.create(TenantSettings, name="core_settings", pk='id')
    
    return {
        'tenant_users': tenant_users,
        'permissions': permissions,
        'settings': settings
    }
