from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import text

from app.api.routes import router
from app.core.config import get_settings
from app.core.database import Base, SessionLocal, engine
from app.models import booking, customer, reservation, room, table, venue, whatsapp  # noqa: F401
from app.services.seed_service import ensure_default_venue_setup


settings = get_settings()
settings.validate_runtime()


def ensure_runtime_schema() -> None:
    with engine.begin() as connection:
        connection.execute(text("ALTER TABLE venues DROP CONSTRAINT IF EXISTS venues_name_key"))
        connection.execute(text("ALTER TABLE venues ADD COLUMN IF NOT EXISTS portal_tenant_id VARCHAR(80)"))
        connection.execute(text("ALTER TABLE venues ADD COLUMN IF NOT EXISTS portal_tenant_slug VARCHAR(120)"))
        connection.execute(
            text("ALTER TABLE venues ADD COLUMN IF NOT EXISTS layout_policy_applied BOOLEAN NOT NULL DEFAULT FALSE")
        )
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_name VARCHAR(120)"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_x INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_y INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_width INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_height INTEGER"))
        connection.execute(
            text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS counter_visible BOOLEAN NOT NULL DEFAULT TRUE")
        )
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_name VARCHAR(120)"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_x INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_y INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_width INTEGER"))
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_height INTEGER"))
        connection.execute(
            text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS entrance_visible BOOLEAN NOT NULL DEFAULT TRUE")
        )
        connection.execute(text("ALTER TABLE rooms ADD COLUMN IF NOT EXISTS background_image_data_url TEXT"))
        connection.execute(text("ALTER TABLE tables ADD COLUMN IF NOT EXISTS shape VARCHAR(20) NOT NULL DEFAULT 'square'"))
        connection.execute(
            text("ALTER TABLE tables ADD COLUMN IF NOT EXISTS rotation_degrees DOUBLE PRECISION NOT NULL DEFAULT 0")
        )
        connection.execute(
            text(
                """
                CREATE UNIQUE INDEX IF NOT EXISTS uq_venues_portal_tenant_id
                ON venues (portal_tenant_id)
                WHERE portal_tenant_id IS NOT NULL
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_assistant_prompt TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_business_account_id TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_business_id TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_phone_number_id TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_access_token TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_display_phone_number TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                ALTER TABLE venue_booking_settings
                ADD COLUMN IF NOT EXISTS whatsapp_verified_name TEXT NOT NULL DEFAULT ''
                """
            )
        )
        connection.execute(
            text(
                """
                CREATE INDEX IF NOT EXISTS ix_venue_booking_settings_whatsapp_phone_number_id
                ON venue_booking_settings (whatsapp_phone_number_id)
                """
            )
        )
        connection.execute(
            text(
                """
                CREATE UNIQUE INDEX IF NOT EXISTS uq_venue_booking_settings_whatsapp_phone_number_id
                ON venue_booking_settings (whatsapp_phone_number_id)
                WHERE whatsapp_phone_number_id <> ''
                """
            )
        )
        connection.execute(text("ALTER TABLE whatsapp_event_logs ADD COLUMN IF NOT EXISTS venue_id INTEGER REFERENCES venues(id)"))
        connection.execute(
            text("CREATE INDEX IF NOT EXISTS ix_whatsapp_event_logs_venue_id ON whatsapp_event_logs (venue_id)")
        )
        connection.execute(
            text(
                """
                CREATE INDEX IF NOT EXISTS ix_whatsapp_assistant_turns_venue_contact_created
                ON whatsapp_assistant_turns (venue_id, contact_phone, created_at DESC, id DESC)
                """
            )
        )
        connection.execute(text("ALTER TABLE whatsapp_booking_sessions DROP CONSTRAINT IF EXISTS whatsapp_booking_sessions_contact_phone_key"))
        connection.execute(text("DROP INDEX IF EXISTS ix_whatsapp_booking_sessions_contact_phone"))
        connection.execute(
            text(
                """
                CREATE INDEX IF NOT EXISTS ix_whatsapp_booking_sessions_contact_phone
                ON whatsapp_booking_sessions (contact_phone)
                """
            )
        )
        connection.execute(
            text(
                """
                CREATE UNIQUE INDEX IF NOT EXISTS uq_whatsapp_booking_sessions_contact_phone_venue_id
                ON whatsapp_booking_sessions (contact_phone, venue_id)
                """
            )
        )


@asynccontextmanager
async def lifespan(_: FastAPI):
    Base.metadata.create_all(bind=engine)
    ensure_runtime_schema()
    db = SessionLocal()
    try:
        ensure_default_venue_setup(db)
    finally:
        db.close()
    yield


app = FastAPI(title=settings.app_name, version="0.1.0", lifespan=lifespan)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins_list,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(router)
