from __future__ import annotations

from typing import Any

from sqlalchemy import create_engine, text
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session, sessionmaker

from config.base import Config


CONTROL_DATABASE_URL = Config.CONTROL_SQLALCHEMY_DATABASE_URI

_engine = None
_SessionFactory = None


def get_control_plane_engine():
    global _engine
    if _engine is None:
        _engine = create_engine(
            CONTROL_DATABASE_URL,
            pool_pre_ping=True,
            pool_recycle=1800,
            future=True,
        )
    return _engine


def get_control_plane_session() -> Session:
    global _SessionFactory
    if _SessionFactory is None:
        _SessionFactory = sessionmaker(
            bind=get_control_plane_engine(),
            autocommit=False,
            autoflush=False,
            future=True,
        )
    return _SessionFactory()


def _normalize_hostname(hostname: str | None) -> str | None:
    if not hostname:
        return None
    value = hostname.strip().lower()
    if not value:
        return None
    if "://" in value:
        value = value.split("://", 1)[1]
    value = value.split("/", 1)[0]
    value = value.split(":", 1)[0]
    return value or None


def resolve_tenant_by_host(hostname: str | None) -> dict[str, Any] | None:
    normalized = _normalize_hostname(hostname)
    if not normalized:
        return None

    session = None
    try:
        session = get_control_plane_session()
        row = session.execute(
            text(
                """
                SELECT td.tenant_id, td.routing_key, td.domain
                FROM tenant_domains td
                WHERE td.domain = :domain
                LIMIT 1
                """
            ),
            {"domain": normalized},
        ).mappings().first()
        return dict(row) if row else None
    except SQLAlchemyError:
        return None
    finally:
        if session is not None:
            session.close()


def get_tenant_assignment(routing_key: str | None) -> dict[str, Any] | None:
    if not routing_key:
        return None

    session = None
    try:
        session = get_control_plane_session()
        row = session.execute(
            text(
                """
                SELECT tenant_id, routing_key, server_role, tenant_db_name, files_base_path
                FROM tenant_assignments
                WHERE routing_key = :routing_key
                ORDER BY CASE WHEN server_role = 'primary' THEN 0 ELSE 1 END, id ASC
                LIMIT 1
                """
            ),
            {"routing_key": routing_key},
        ).mappings().first()
        return dict(row) if row else None
    except SQLAlchemyError:
        return None
    finally:
        if session is not None:
            session.close()
