import os

from flask import Flask
from flask import redirect, url_for, session, request
from flask_wtf.csrf import CSRFProtect
from sqlalchemy import inspect, text

from config import Config
from models import db
from blueprints.auth import auth_bp
from blueprints.usuarios import usuarios_bp
from blueprints.mantenedores import mantenedores_bp
from blueprints.inmobiliarias import inmobiliarias_bp
from blueprints.vendedores import vendedores_bp
from blueprints.temas import temas_bp
from blueprints.asignaciones import asignaciones_bp
from blueprints.core import core_bp
from blueprints.programar_envio import programar_bp
from blueprints.estructura_temas import estructura_temas_bp
from blueprints.reportes import reportes_bp
from blueprints.cliente_scope import get_global_cliente, opciones_tipos_cliente

csrf = CSRFProtect()


DEFAULT_TIPOS_CLIENTE = [
    "Inmobiliario Usuario Final",
    "Inmobiliario Inversionistas",
    "Nobel",
    "Pepsico",
]


def _ensure_app_schema(app: Flask) -> None:
    """Ajustes idempotentes de tablas/campos para la app web."""
    with app.app_context():
        try:
            inspector = inspect(db.engine)
            raw_tables = inspector.get_table_names()
            table_by_lower = {t.lower(): t for t in raw_tables}

            users_table = table_by_lower.get("users")
            inmo_table = table_by_lower.get("inmobiliarias")
            temas_table = table_by_lower.get("temas")

            cols_inmo = set()

            if users_table:
                cols_users = {c["name"].lower() for c in inspector.get_columns(users_table)}
                if "apellido" not in cols_users:
                    db.session.execute(text(f"ALTER TABLE `{users_table}` ADD COLUMN apellido VARCHAR(120) NULL"))
                if "correo" not in cols_users:
                    db.session.execute(text(f"ALTER TABLE `{users_table}` ADD COLUMN correo VARCHAR(150) NULL"))

                db.session.execute(text(f"ALTER TABLE `{users_table}` MODIFY COLUMN rol VARCHAR(30) NULL DEFAULT 'UsuarioEmpresa'"))
                db.session.execute(text(f"UPDATE `{users_table}` SET rol='Administrador' WHERE LOWER(rol)='admin'"))
                db.session.execute(text(f"UPDATE `{users_table}` SET rol='UsuarioEmpresa' WHERE LOWER(rol)='user'"))

            if inmo_table:
                cols_inmo = {c["name"].lower() for c in inspector.get_columns(inmo_table)}
                if "cliente" not in cols_inmo:
                    db.session.execute(text(f"ALTER TABLE `{inmo_table}` ADD COLUMN cliente VARCHAR(100) NULL"))
                    cols_inmo.add("cliente")

            if temas_table:
                cols_temas = {c["name"].lower() for c in inspector.get_columns(temas_table)}
                if "cliente" not in cols_temas:
                    db.session.execute(text(f"ALTER TABLE `{temas_table}` ADD COLUMN cliente VARCHAR(100) NULL"))

            db.session.execute(text("""
                CREATE TABLE IF NOT EXISTS aw_tipos_cliente (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    nombre VARCHAR(120) NOT NULL,
                    UNIQUE KEY uq_aw_tipos_cliente_nombre (nombre)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            """))

            db.session.execute(text("""
                CREATE TABLE IF NOT EXISTS user_empresas (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    user_id INT NOT NULL,
                    inmobiliaria_id INT NOT NULL,
                    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    UNIQUE KEY uq_user_empresas_user_inmobiliaria (user_id, inmobiliaria_id),
                    INDEX ix_user_empresas_user_id (user_id),
                    INDEX ix_user_empresas_inmobiliaria_id (inmobiliaria_id)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            """))

            db.session.execute(text("""
                CREATE TABLE IF NOT EXISTS aw_empresa_programacion_temas (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    empresa_id INT NOT NULL,
                    tema VARCHAR(255) NOT NULL,
                    orden INT NOT NULL DEFAULT 1,
                    fecha_activacion_tema DATE NULL,
                    fecha_propuesta DATE NULL,
                    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    INDEX ix_aw_programacion_empresa_id (empresa_id),
                    INDEX ix_aw_programacion_orden (empresa_id, orden)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            """))

            for nombre in DEFAULT_TIPOS_CLIENTE:
                db.session.execute(
                    text("INSERT IGNORE INTO aw_tipos_cliente (nombre) VALUES (:nombre)"),
                    {"nombre": nombre},
                )

            if temas_table:
                db.session.execute(text(f"""
                    INSERT IGNORE INTO aw_tipos_cliente (nombre)
                    SELECT DISTINCT TRIM(cliente)
                    FROM `{temas_table}`
                    WHERE cliente IS NOT NULL AND TRIM(cliente) <> ''
                """))

            if inmo_table and "cliente" in cols_inmo:
                db.session.execute(text(f"""
                    INSERT IGNORE INTO aw_tipos_cliente (nombre)
                    SELECT DISTINCT TRIM(cliente)
                    FROM `{inmo_table}`
                    WHERE cliente IS NOT NULL AND TRIM(cliente) <> ''
                """))

            db.session.commit()
        except Exception as exc:
            db.session.rollback()
            app.logger.warning("No se pudo auto-migrar esquema de app: %s", exc)


def create_app():
    app = Flask(__name__, static_folder="assets", static_url_path="/assets")
    app.config.from_object(Config)
    db.init_app(app)
    csrf.init_app(app)

    _ensure_app_schema(app)

    app.register_blueprint(auth_bp)
    app.register_blueprint(usuarios_bp, url_prefix="/usuarios")
    app.register_blueprint(mantenedores_bp, url_prefix="/mantenedores")
    app.register_blueprint(inmobiliarias_bp, url_prefix="/empresas")
    app.register_blueprint(vendedores_bp, url_prefix="/vendedores")
    app.register_blueprint(temas_bp, url_prefix="/temas")
    app.register_blueprint(asignaciones_bp, url_prefix="/asignaciones")
    app.register_blueprint(estructura_temas_bp, url_prefix="/estructura_temas")
    app.register_blueprint(core_bp, url_prefix="")
    app.register_blueprint(programar_bp)
    app.register_blueprint(reportes_bp, url_prefix="/reportes")

    @app.context_processor
    def inject_global_cliente_filter():
        return {
            "global_tipo_cliente": get_global_cliente(),
            "global_tipos_cliente": opciones_tipos_cliente(),
        }

    @app.get("/health")
    def health():
        return {"ok": True}

    @app.get("/")
    def index():
        return redirect(url_for("core.home") if "uid" in session else url_for("auth.login"))

    @app.route("/inmobiliarias", defaults={"subpath": ""})
    @app.route("/inmobiliarias/<path:subpath>")
    def redirect_inmobiliarias_legacy(subpath):
        target = "/empresas"
        if subpath:
            target = f"{target}/{subpath}"
        qs = request.query_string.decode()
        if qs:
            target = f"{target}?{qs}"
        return redirect(target, code=302)

    @app.get("/logout")
    def logout_root():
        session.clear()
        return redirect(url_for("auth.login"))

    return app


app = create_app()

if __name__ == "__main__":
    app.run(
        host=os.getenv("FLASK_HOST", "127.0.0.1"),
        port=int(os.getenv("FLASK_PORT", "5000")),
        debug=os.getenv("FLASK_DEBUG", "0") == "1",
    )


