# /home/Autopartes/pos/middleware_tenant.py
"""Subdomain-based tenant resolver middleware for Nexus POS.

Routes like refac-lopez.nexusautoparts.com are resolved to a tenant_id
via the `tenants.subdomain` column in nexus_master.

Resolution order:
  1. X-Tenant-Subdomain header (set by nginx)
  2. Host header subdomain extraction (fallback for dev)
  3. ?tenant=ID URL parameter (legacy / direct access)
"""

import re
from flask import request, g, redirect
from tenant_db import get_master_conn

# Domains that should NOT be treated as tenant subdomains
_RESERVED = {'www', 'api', 'admin', 'mail', 'staging', 'dev', 'nexus', 'pos', 'app', 'dashboard'}

# Cache: subdomain -> {tenant_id, name} (cleared on app restart)
_subdomain_cache = {}


def _extract_subdomain():
    """Extract tenant subdomain from request. Returns subdomain string or None."""
    # 1. Nginx header (most reliable in production)
    sub = request.headers.get('X-Tenant-Subdomain', '').strip().lower()
    if sub and sub not in _RESERVED:
        return sub

    # 2. Parse from Host header (dev fallback)
    host = request.host.split(':')[0].lower()  # strip port
    # Match: <subdomain>.nexusautoparts.com or <subdomain>.localhost
    parts = host.split('.')
    if len(parts) >= 3:
        # e.g. refac-lopez.nexusautoparts.com -> refac-lopez
        candidate = parts[0]
        if candidate not in _RESERVED:
            return candidate
    elif len(parts) == 2 and parts[1] == 'localhost':
        # e.g. refac-lopez.localhost for local dev
        candidate = parts[0]
        if candidate not in _RESERVED:
            return candidate

    return None


def _lookup_tenant_by_subdomain(subdomain):
    """Look up tenant_id and name from subdomain. Returns dict or None."""
    if subdomain in _subdomain_cache:
        return _subdomain_cache[subdomain]

    try:
        conn = get_master_conn()
        cur = conn.cursor()
        cur.execute(
            "SELECT id, name FROM tenants WHERE LOWER(subdomain) = %s AND is_active = true",
            (subdomain,)
        )
        row = cur.fetchone()
        cur.close()
        conn.close()

        if row:
            result = {'tenant_id': row[0], 'name': row[1]}
            _subdomain_cache[subdomain] = result
            return result
    except Exception:
        pass

    return None


def clear_subdomain_cache():
    """Clear the subdomain lookup cache (call after tenant updates)."""
    _subdomain_cache.clear()


def resolve_tenant():
    """Flask before_request handler: resolve tenant from subdomain or URL param.

    Sets on flask.g:
      - g.tenant_id (int or None)
      - g.tenant_name (str or None)
      - g.tenant_subdomain (str or None)
    """
    g.tenant_id = None
    g.tenant_name = None
    g.tenant_subdomain = None

    # Skip for static files and health check
    if request.path.startswith('/pos/static/') or request.path == '/pos/health':
        return

    subdomain = _extract_subdomain()

    if subdomain:
        tenant = _lookup_tenant_by_subdomain(subdomain)
        if tenant:
            g.tenant_id = tenant['tenant_id']
            g.tenant_name = tenant['name']
            g.tenant_subdomain = subdomain
            return
        else:
            # Unknown subdomain: just continue without tenant (login will ask for it)
            pass

    # Fallback: ?tenant=ID URL parameter
    tenant_param = request.args.get('tenant')
    if tenant_param:
        try:
            g.tenant_id = int(tenant_param)
        except (ValueError, TypeError):
            pass
