import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager

db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = "admin.login"
login_manager.login_message = "Please log in to access the admin panel."
login_manager.login_message_category = "warning"


def create_app():
    app = Flask(__name__)
    app.config.from_object("config.Config")

    db.init_app(app)
    login_manager.init_app(app)

    # Register Blueprints (Controllers)
    from app.controllers.main_controller import main_bp
    from app.controllers.admin_controller import admin_bp

    app.register_blueprint(main_bp)
    app.register_blueprint(admin_bp, url_prefix="/admin")

    # Jinja filter: turns a pasted YouTube / Vimeo / direct video link into
    # an embeddable {kind, embed_src, watch_url} dict (see app/utils.py)
    from app.utils import parse_video_embed
    app.jinja_env.filters["video_embed"] = parse_video_embed

    # Context processor: makes site settings available in every template
    from app.models import SiteSetting
    from datetime import datetime

    @app.context_processor
    def inject_settings():
        settings = SiteSetting.get_settings()
        return dict(settings=settings, current_year=datetime.utcnow().year)

    with app.app_context():
        db.create_all()       # creates any brand-new tables
        _auto_migrate()        # adds any new columns to tables that already existed
        _seed_defaults()

    return app


def _auto_migrate():
    """Lightweight schema sync for MySQL: for every table that already
    exists, add any column defined on the model but missing from the
    live database. This lets the app pick up new fields (e.g. a phone
    number on Team, or new SiteSetting columns) on an existing database
    without a full migration tool. New tables are already handled by
    db.create_all() above, so this only ever adds columns, never drops
    or renames anything.
    """
    from sqlalchemy import inspect, text

    inspector = inspect(db.engine)
    existing_tables = set(inspector.get_table_names())
    added = []

    for table in db.metadata.tables.values():
        if table.name not in existing_tables:
            continue  # brand-new table — db.create_all() already made it

        existing_cols = {c["name"] for c in inspector.get_columns(table.name)}
        for col in table.columns:
            if col.name in existing_cols:
                continue
            try:
                col_type = col.type.compile(dialect=db.engine.dialect)
                ddl = f"ALTER TABLE `{table.name}` ADD COLUMN `{col.name}` {col_type}"
                with db.engine.begin() as conn:
                    conn.execute(text(ddl))
                added.append(f"{table.name}.{col.name}")
            except Exception as exc:  # pragma: no cover - best effort
                print(f"[auto-migrate] could not add {table.name}.{col.name}: {exc}")

    if added:
        print(f"[auto-migrate] added columns: {', '.join(added)}")
        _post_migration_fixups(added)


def _post_migration_fixups(added_columns):
    """Newly-added columns start out NULL for existing rows. A couple of
    them need a sane default filled in so already-published content
    doesn't silently disappear from the public site."""
    from sqlalchemy import text

    with db.engine.begin() as conn:
        if "publications.is_published" in added_columns:
            conn.execute(text(
                "UPDATE publications SET is_published = 1 WHERE is_published IS NULL"
            ))
        if "site_settings.map_embed_url" in added_columns:
            conn.execute(text(
                "UPDATE site_settings SET map_embed_url = "
                "'https://www.google.com/maps?q=Kathmandu,Nepal&output=embed' "
                "WHERE map_embed_url IS NULL OR map_embed_url = ''"
            ))


# def _seed_defaults():
#     """Create the settings row / default admin the first time the app runs,
#     so the site is usable immediately after `flask run` without manual SQL."""
#     from app.models import SiteSetting, Admin
#     from werkzeug.security import generate_password_hash
#     from flask import current_app

#     if SiteSetting.query.first() is None:
#         db.session.add(SiteSetting(
#             site_name="Pashupati Legal Services",
#             phone="+977-1-4123456",
#             email="info@pashupatilegal.com",
#             address="Kathmandu, Nepal",
#             office_hours="Sun - Fri: 10:00 AM - 5:00 PM",
#             registration_number="124344656",
#             facebook_url="https://facebook.com/",
#             instagram_url="https://instagram.com/",
#             home_headline="Trusted Legal Counsel You Can Rely On",
#             home_description=(
#                 "Pashupati Legal Services provides dependable, ethical and result-driven "
#                 "legal representation across Nepal, guiding individuals, families and "
#                 "businesses through even the most complex legal matters with clarity and care."
#             ),
#             about_description=(
#                 "Pashupati Legal Services was founded on the belief that every client "
#                 "deserves honest counsel and dedicated representation. Our team of "
#                 "experienced advocates blends deep legal knowledge with a genuine "
#                 "commitment to protecting our clients' rights and interests."
#             ),
#             map_embed_url="https://www.google.com/maps?q=Kathmandu,Nepal&output=embed",
#         ))
#         db.session.commit()

#     if Admin.query.first() is None:
#         db.session.add(Admin(
#             username=current_app.config["DEFAULT_ADMIN_USERNAME"],
#             password_hash=generate_password_hash(current_app.config["DEFAULT_ADMIN_PASSWORD"]),
#         ))
#         db.session.commit()
def _seed_defaults():
    """Create the settings row / default admin the first time the app runs,
    so the site is usable immediately after `flask run` without manual SQL."""
    from app.models import SiteSetting, Admin
    from werkzeug.security import generate_password_hash
    from flask import current_app

    if SiteSetting.query.first() is None:
        db.session.add(SiteSetting(
            site_name="Pashupati Legal Services",
            phone="+977-1-4123456",
            email="info@pashupatilegal.com",
            address="Kathmandu, Nepal",
            office_hours="Sun - Fri: 10:00 AM - 5:00 PM",
            registration_number="124344656",
            facebook_url="https://facebook.com/",
            instagram_url="https://instagram.com/",
            home_headline="Trusted Legal Counsel You Can Rely On",
            home_description=(
                "Pashupati Legal Services provides dependable, ethical and result-driven "
                "legal representation across Nepal, guiding individuals, families and "
                "businesses through even the most complex legal matters with clarity and care."
            ),
            about_description=(
                "Pashupati Legal Services was founded on the belief that every client "
                "deserves honest counsel and dedicated representation. Our team of "
                "experienced advocates blends deep legal knowledge with a genuine "
                "commitment to protecting our clients' rights and interests."
            ),
            map_embed_url="https://www.google.com/maps?q=Kathmandu,Nepal&output=embed",
        ))
        db.session.commit()

    if Admin.query.first() is None:
        # Uses config values if present, otherwise falls back to defaults
        admin_user = current_app.config.get("DEFAULT_ADMIN_USERNAME", "admin")
        admin_pass = current_app.config.get("DEFAULT_ADMIN_PASSWORD", "Admin@12345")

        db.session.add(Admin(
            username=admin_user,
            password_hash=generate_password_hash(admin_pass),
        ))
        db.session.commit()