import os
import logging
from flask import Flask
from flask_session import Session
from models import db, Settings, Look

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key-123')
app.config['CHARACTERS_DIR'] = 'data/characters'
app.config['CLOTHING_DIR'] = 'data/clothing'
app.config['ACTIONS_DIR'] = 'data/actions'
app.config['STYLES_DIR'] = 'data/styles'
app.config['SCENES_DIR'] = 'data/scenes'
app.config['DETAILERS_DIR'] = 'data/detailers'
app.config['CHECKPOINTS_DIR'] = 'data/checkpoints'
app.config['LOOKS_DIR'] = 'data/looks'
app.config['PRESETS_DIR'] = 'data/presets'
app.config['COMFYUI_URL'] = os.environ.get('COMFYUI_URL', 'http://127.0.0.1:8188')
app.config['ILLUSTRIOUS_MODELS_DIR'] = '/ImageModels/Stable-diffusion/Illustrious/'
app.config['NOOB_MODELS_DIR'] = '/ImageModels/Stable-diffusion/Noob/'
app.config['LORA_DIR'] = '/ImageModels/lora/Illustrious/Looks/'

# Server-side session configuration to avoid cookie size limits
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = os.path.join(app.config['UPLOAD_FOLDER'], '../flask_session')
app.config['SESSION_PERMANENT'] = False

db.init_app(app)
Session(app)

# ---------------------------------------------------------------------------
# Logging
# ---------------------------------------------------------------------------
log_level_str = os.environ.get('LOG_LEVEL', 'INFO').upper()
log_level = getattr(logging, log_level_str, logging.INFO)

logging.basicConfig(
    level=log_level,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
)
logger = logging.getLogger('gaze')
logger.setLevel(log_level)

# ---------------------------------------------------------------------------
# Register all routes
# ---------------------------------------------------------------------------
from routes import register_routes
register_routes(app)

# ---------------------------------------------------------------------------
# Startup
# ---------------------------------------------------------------------------
if __name__ == '__main__':
    from services.mcp import ensure_mcp_server_running, ensure_character_mcp_server_running
    from services.job_queue import init_queue_worker
    from services.sync import (
        sync_characters, sync_outfits, sync_actions, sync_styles,
        sync_detailers, sync_scenes, sync_looks, sync_checkpoints, sync_presets,
    )

    ensure_mcp_server_running()
    ensure_character_mcp_server_running()
    init_queue_worker(app)
    with app.app_context():
        from sqlalchemy import text

        os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
        os.makedirs(app.config['SESSION_FILE_DIR'], exist_ok=True)
        db.create_all()

        # --- Helper for safe column additions ---
        def _add_column(table, column, col_type):
            try:
                db.session.execute(text(f'ALTER TABLE {table} ADD COLUMN {column} {col_type}'))
                db.session.commit()
                logger.info("Added %s.%s column", table, column)
            except Exception as e:
                db.session.rollback()
                err_str = str(e).lower()
                if 'duplicate column name' in err_str or 'already exists' in err_str:
                    pass  # Column already exists, expected
                else:
                    logger.warning("Migration failed (%s.%s): %s", table, column, e)

        # --- All migrations (grouped before syncs) ---
        _add_column('character', 'active_outfit', "VARCHAR(100) DEFAULT 'default'")
        _add_column('action', 'default_fields', 'JSON')
        _add_column('checkpoint', 'data', 'JSON')
        _add_column('look', 'character_ids', 'JSON')

        # Settings columns
        for col_name, col_type in [
            ('llm_provider',        "VARCHAR(50) DEFAULT 'openrouter'"),
            ('local_base_url',      'VARCHAR(255)'),
            ('local_model',         'VARCHAR(100)'),
            ('lora_dir_characters', "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Looks'"),
            ('lora_dir_outfits',    "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Clothing'"),
            ('lora_dir_actions',    "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Poses'"),
            ('lora_dir_styles',     "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Styles'"),
            ('lora_dir_scenes',     "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Backgrounds'"),
            ('lora_dir_detailers',  "VARCHAR(500) DEFAULT '/ImageModels/lora/Illustrious/Detailers'"),
            ('checkpoint_dirs',     "VARCHAR(1000) DEFAULT '/ImageModels/Stable-diffusion/Illustrious,/ImageModels/Stable-diffusion/Noob'"),
            ('default_checkpoint',  'VARCHAR(500)'),
            ('api_key',             'VARCHAR(255)'),
        ]:
            _add_column('settings', col_name, col_type)

        # is_favourite / is_nsfw on all resource tables
        for tbl in ['character', 'look', 'outfit', 'action', 'style', 'scene', 'detailer', 'checkpoint', 'preset']:
            _add_column(tbl, 'is_favourite', 'BOOLEAN DEFAULT 0')
            _add_column(tbl, 'is_nsfw', 'BOOLEAN DEFAULT 0')

        # Ensure settings exist
        if not Settings.query.first():
            db.session.add(Settings())
            db.session.commit()
            logger.info("Created default settings")

        # Log default checkpoint
        settings = Settings.query.first()
        if settings and settings.default_checkpoint:
            logger.info("Default checkpoint: %s", settings.default_checkpoint)
        else:
            logger.info("No default checkpoint set in database")

        # --- Sync all categories ---
        sync_characters()
        sync_outfits()
        sync_actions()
        sync_styles()
        sync_detailers()
        sync_scenes()
        sync_looks()
        sync_checkpoints()
        sync_presets()

        # --- Post-sync data migration: character_id → character_ids ---
        try:
            looks_with_old_field = Look.query.filter(Look.character_id.isnot(None)).all()
            migrated_count = 0
            for look in looks_with_old_field:
                if not look.character_ids:
                    look.character_ids = []
                if look.character_id and look.character_id not in look.character_ids:
                    look.character_ids.append(look.character_id)
                    migrated_count += 1
            if migrated_count > 0:
                db.session.commit()
                logger.info("Migrated %d looks from character_id to character_ids", migrated_count)
        except Exception as e:
            logger.debug("Migration note (character_ids data): %s", e)

    app.run(debug=True, host='0.0.0.0', port=5000)
