"""
Facade over :mod:`storage.db_repo`.

* **Published** (`insert_user_profiling_row`) — API / forced runs; admins read `dbo.user_profiling`.
* **Staging** (`insert_user_profiling_staging_row`) — scheduled batch only; use
  :meth:`ProfilingRepository.publish_staging_to_published` after a full scan.

``db`` may be a SQLAlchemy :class:`~sqlalchemy.engine.Engine` to bind the repository
to that engine (e.g. tests). Other values use the env-driven singleton.
"""

from __future__ import annotations

from typing import Any, Dict, Optional

from sqlalchemy.engine import Engine

from storage.db_model import UserProfiling, UserProfilingStaging, UserProfilingTracker
from storage.db_repo import ProfilingRepository, get_profiling_repository, profile_data_to_json


def _profiling_repo(db) -> ProfilingRepository:
    if isinstance(db, Engine):
        return get_profiling_repository(db)
    return get_profiling_repository()

USER_PROFILING_TABLE = UserProfiling.__tablename__
USER_PROFILING_STAGING_TABLE = UserProfilingStaging.__tablename__
USER_PROFILING_TRACKER_TABLE = UserProfilingTracker.__tablename__


def ensure_user_profiling_table(db) -> None:
    _profiling_repo(db).ensure_tables()


def ensure_user_profiling_tracker_table(db) -> None:
    _profiling_repo(db).ensure_tables()


def ensure_profiling_storage_tables(db) -> None:
    _profiling_repo(db).ensure_tables()


def tracker_should_skip_scheduled_run(db, user_id: int, recency_days: int) -> bool:
    return _profiling_repo(db).should_skip_scheduled_run(user_id, recency_days)


def upsert_user_profiling_tracker(db, user_id: int) -> None:
    _profiling_repo(db).touch_tracker(user_id)


def insert_user_profiling_row(
    db,
    user_id: int,
    profile_data: Dict[str, Any],
    deep_analysis_markdown: Optional[str] = None,
) -> None:
    """Upsert **published** dbo.user_profiling + tracker (API / forced)."""
    _profiling_repo(db).upsert_published(user_id, profile_data, deep_analysis_markdown)


def insert_user_profiling_staging_row(
    db,
    user_id: int,
    profile_data: Dict[str, Any],
    deep_analysis_markdown: Optional[str] = None,
) -> None:
    """Upsert **staging** only (batch job). Does not touch tracker or published."""
    _profiling_repo(db).upsert_staging(user_id, profile_data, deep_analysis_markdown)


def publish_profiling_staging(db) -> None:
    """Promote staging → published in one DB transaction (call after full batch scan)."""
    _profiling_repo(db).publish_staging_to_published()


def truncate_profiling_staging(db) -> None:
    """Clear staging at the start of a new batch from user id 0."""
    _profiling_repo(db).truncate_staging()


__all__ = [
    "USER_PROFILING_TABLE",
    "USER_PROFILING_STAGING_TABLE",
    "USER_PROFILING_TRACKER_TABLE",
    "ensure_profiling_storage_tables",
    "ensure_user_profiling_table",
    "ensure_user_profiling_tracker_table",
    "insert_user_profiling_row",
    "insert_user_profiling_staging_row",
    "profile_data_to_json",
    "publish_profiling_staging",
    "tracker_should_skip_scheduled_run",
    "truncate_profiling_staging",
    "upsert_user_profiling_tracker",
]
