"""
Centralized database initialization module.

This module provides a single entry point for database initialization.
In the future, this will be replaced with Alembic migrations for better
version control and schema evolution.

TODO: Implement Alembic migrations for production use
"""

from typing import Optional
from loguru import logger
from sqlalchemy import Engine, inspect
from sqlalchemy.orm import Session

from ..database.models import Base


def initialize_database(
    engine: Engine,
    db_session: Optional[Session] = None,
) -> None:
    """
    Initialize database tables if they don't exist.

    This is a temporary solution until Alembic migrations are implemented.
    Currently creates all tables defined in the models if they don't exist.

    Args:
        engine: SQLAlchemy engine for the database
        db_session: Optional database session for settings initialization
    """
    inspector = inspect(engine)
    existing_tables = inspector.get_table_names()

    logger.info(
        f"Initializing database with {len(existing_tables)} existing tables"
    )
    logger.debug(
        f"Base.metadata has {len(Base.metadata.tables)} tables defined"
    )

    # Create all tables (including news tables) - let SQLAlchemy handle dependencies
    # checkfirst=True ensures existing tables are not recreated
    logger.info("Creating database tables")
    Base.metadata.create_all(engine, checkfirst=True)

    # Run migrations for existing tables
    _run_migrations(engine)

    # Check what was created (need new inspector to avoid caching)
    new_inspector = inspect(engine)
    new_tables = new_inspector.get_table_names()
    logger.info(f"After initialization: {len(new_tables)} tables exist")

    # Initialize default settings if session provided
    if db_session:
        try:
            _initialize_default_settings(db_session)
        except Exception as e:
            logger.warning(f"Could not initialize default settings: {e}")

    logger.info("Database initialization complete")


def _initialize_default_settings(db_session: Session) -> None:
    """
    Initialize default settings from the defaults file.

    Args:
        db_session: Database session to use for settings initialization
    """
    from ..settings.manager import SettingsManager

    try:
        settings_mgr = SettingsManager(db_session)

        # Check if we need to update settings
        if settings_mgr.db_version_matches_package():
            logger.debug("Settings version matches package, skipping update")
            return

        logger.info("Loading default settings into database")

        # Load settings from defaults file
        # This will not overwrite existing settings but will add new ones
        settings_mgr.load_from_defaults_file(overwrite=False, delete_extra=True)

        # Update the saved version
        settings_mgr.update_db_version()

        logger.info("Default settings initialized successfully")

    except Exception:
        logger.exception("Error initializing default settings")


def check_database_schema(engine: Engine) -> dict:
    """
    Check the current database schema and return information about tables.

    Args:
        engine: SQLAlchemy engine for the database

    Returns:
        Dictionary with schema information including tables and their columns
    """
    inspector = inspect(engine)
    schema_info = {
        "tables": {},
        "missing_tables": [],
        "has_news_tables": False,
    }

    # Check core tables
    for table_name in Base.metadata.tables.keys():
        if inspector.has_table(table_name):
            columns = [col["name"] for col in inspector.get_columns(table_name)]
            schema_info["tables"][table_name] = columns
        else:
            schema_info["missing_tables"].append(table_name)

    # Check if news tables exist
    news_tables = ["news_subscription", "news_card", "news_interest"]
    for table_name in news_tables:
        if table_name in schema_info["tables"]:
            schema_info["has_news_tables"] = True
            break

    return schema_info


def _add_column_if_not_exists(
    engine: Engine,
    table_name: str,
    column_name: str,
    column_type: str,
    default: str = None,
) -> bool:
    """
    Add a column to a table if it doesn't already exist.

    Uses SQLAlchemy's DDL capabilities for dialect-aware column addition.

    Args:
        engine: SQLAlchemy engine
        table_name: Name of the table to modify
        column_name: Name of the column to add
        column_type: SQLAlchemy-compatible type string (e.g., 'INTEGER', 'TEXT')
        default: Optional default value clause

    Returns:
        True if column was added, False if it already existed
    """
    from sqlalchemy.schema import CreateColumn, Column
    from sqlalchemy import Integer, String

    inspector = inspect(engine)
    existing_columns = {
        col["name"] for col in inspector.get_columns(table_name)
    }

    if column_name in existing_columns:
        return False

    # Build column definition using SQLAlchemy types
    type_map = {
        "INTEGER": Integer(),
        "TEXT": String(),
    }
    col_type = type_map.get(column_type.upper(), String())
    column = Column(column_name, col_type)

    # Use CreateColumn to get dialect-aware DDL
    compiled = CreateColumn(column).compile(dialect=engine.dialect)
    column_def = str(compiled).strip()

    # Add default clause if specified
    if default is not None:
        column_def = f"{column_def} DEFAULT {default}"

    try:
        with engine.begin() as conn:
            # Use DDL class for proper execution
            from sqlalchemy import DDL

            ddl = DDL(f"ALTER TABLE {table_name} ADD {column_def}")
            conn.execute(ddl)
        logger.info(f"Added column {column_name} to {table_name} table")
        return True
    except Exception as e:
        logger.debug(f"Migration for {column_name} skipped: {e}")
        return False


def _run_migrations(engine: Engine) -> None:
    """
    Run database migrations to add missing columns to existing tables.

    This is a simple migration system for adding new columns.
    For more complex migrations, consider using Alembic.
    """
    inspector = inspect(engine)

    # Migration: Add progress tracking columns to task_metadata
    if inspector.has_table("task_metadata"):
        _add_column_if_not_exists(
            engine, "task_metadata", "progress_current", "INTEGER", "0"
        )
        _add_column_if_not_exists(
            engine, "task_metadata", "progress_total", "INTEGER", "0"
        )
        _add_column_if_not_exists(
            engine, "task_metadata", "progress_message", "TEXT"
        )
        _add_column_if_not_exists(
            engine, "task_metadata", "metadata_json", "TEXT"
        )
