"""Render template resolution service.

Used from Celery tasks (sync context) to find the best matching .blend template
for a given category + output type combination.

Cascade priority (first active match wins):
1. Exact:         category_key + output_type_id
2. Category only: category_key + output_type_id IS NULL
3. OT only:       category_key IS NULL + output_type_id
4. Global:        both NULL
5. No template  → caller falls back to factory-settings behavior
"""
import logging

from sqlalchemy import create_engine, select, and_
from sqlalchemy.orm import Session

from app.models.render_template import RenderTemplate
from app.models.system_setting import SystemSetting

logger = logging.getLogger(__name__)

_engine = None


def _get_engine():
    global _engine
    if _engine is None:
        from app.config import settings as app_settings
        _engine = create_engine(app_settings.database_url_sync)
    return _engine


def resolve_template(
    category_key: str | None = None,
    output_type_id: str | None = None,
) -> RenderTemplate | None:
    """Find the best matching active render template.

    Uses sync SQLAlchemy — safe for Celery tasks.
    """
    engine = _get_engine()
    with Session(engine) as session:
        active = RenderTemplate.is_active == True  # noqa: E712

        # 1. Exact match
        if category_key and output_type_id:
            row = session.execute(
                select(RenderTemplate).where(and_(
                    active,
                    RenderTemplate.category_key == category_key,
                    RenderTemplate.output_type_id == output_type_id,
                ))
            ).scalar_one_or_none()
            if row:
                return row

        # 2. Category only
        if category_key:
            row = session.execute(
                select(RenderTemplate).where(and_(
                    active,
                    RenderTemplate.category_key == category_key,
                    RenderTemplate.output_type_id.is_(None),
                ))
            ).scalar_one_or_none()
            if row:
                return row

        # 3. OT only
        if output_type_id:
            row = session.execute(
                select(RenderTemplate).where(and_(
                    active,
                    RenderTemplate.category_key.is_(None),
                    RenderTemplate.output_type_id == output_type_id,
                ))
            ).scalar_one_or_none()
            if row:
                return row

        # 4. Global fallback (both NULL)
        row = session.execute(
            select(RenderTemplate).where(and_(
                active,
                RenderTemplate.category_key.is_(None),
                RenderTemplate.output_type_id.is_(None),
            ))
        ).scalar_one_or_none()
        return row


def get_material_library_path() -> str | None:
    """Read material_library_path from system_settings. Returns None if empty."""
    engine = _get_engine()
    with Session(engine) as session:
        row = session.execute(
            select(SystemSetting).where(SystemSetting.key == "material_library_path")
        ).scalar_one_or_none()
        if row and row.value and row.value.strip():
            return row.value.strip()
        return None
