import logging
from contextlib import asynccontextmanager

from fastapi import FastAPI

from database import engine, Base

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

from api import (
    invoices, suppliers, reports, settings, field_mappings, newbook, sambapos,
    backup, search, resos, calendar_events, residents_table_chart, disputes,
    credit_notes, public, logbook, imap, support, budget, cover_overrides,
    purchase_orders, cost_distributions, ingredients, recipes, food_flags,
    event_orders, external, menus, reconciliation,
)
from api.internal import router as internal_router

from migrations.add_invoice_features import run_migration
from migrations.add_newbook_tables import run_migration as run_newbook_migration
from migrations.add_line_item_search import run_migration as run_search_migration
from migrations.add_sambapos_settings import run_migration as run_sambapos_migration
from migrations.add_sambapos_excluded_items import run_migration as run_sambapos_excluded_migration
from migrations.add_admin_restricted_pages import run_migration as run_admin_pages_migration
from migrations.add_nextcloud_backup import run_migration as run_nextcloud_backup_migration
from migrations.add_price_settings import run_migration as run_price_settings_migration
from migrations.add_resos_integration import run_migration as run_resos_migration
from migrations.add_calendar_events import run_migration as run_calendar_events_migration
from migrations.add_resos_upcoming_sync import run_migration as run_resos_upcoming_sync_migration
from migrations.add_newbook_upcoming_sync import run_migration as run_newbook_upcoming_sync_migration
from migrations.add_residents_table_chart import run_migration as run_residents_table_chart_migration
from migrations.add_rooms_breakdown import run_migration as run_rooms_breakdown_migration
from migrations.add_invoice_disputes import run_migration as run_disputes_migration
from migrations.add_awaiting_replacement_status import run_migration as run_awaiting_replacement_migration
from migrations.add_new_status import run_migration as run_new_status_migration
from migrations.add_dispute_attachment_public_hash import run_migration as run_dispute_attachment_hash_migration
from migrations.add_logbook import run_migration as run_logbook_migration
from migrations.add_imap_integration import run_migration as run_imap_migration
from migrations.add_support_request import run_migration as run_support_migration
from migrations.add_pdf_annotation_settings import run_migration as run_pdf_annotation_settings_migration
from migrations.add_linked_dispute import run_migration as run_linked_dispute_migration
from migrations.add_ocr_post_processing import run_migration as run_ocr_post_processing_migration
from migrations.add_ocr_weight_setting import run_migration as run_ocr_weight_setting_migration
from migrations.add_budget_settings import migrate as run_budget_settings_migration
from migrations.add_cover_overrides import migrate as run_cover_overrides_migration
from migrations.add_purchase_orders import migrate as run_purchase_orders_migration
from migrations.add_supplier_po_fields import migrate as run_supplier_po_fields_migration
from migrations.add_kitchen_details import migrate as run_kitchen_details_migration
from migrations.add_cost_distributions import migrate as run_cost_distributions_migration
from migrations.add_recipe_system import migrate as run_recipe_system_migration
from migrations.add_flag_assessment import migrate as run_flag_assessment_migration
from migrations.add_dish_separation import migrate as run_dish_separation_migration
from migrations.add_step_title import migrate as run_step_title_migration
from migrations.add_gross_sell_price import migrate as run_gross_sell_price_migration
from migrations.add_recipe_ingredient_yield import migrate as run_recipe_ingredient_yield_migration
from migrations.add_recipe_batch_type import migrate as run_recipe_batch_type_migration
from migrations.add_sub_recipe_unit import migrate as run_sub_recipe_unit_migration
from migrations.add_recipe_ingredient_unit import migrate as run_recipe_ingredient_unit_migration
from migrations.add_allergen_keywords import migrate as run_allergen_keywords_migration
from migrations.add_brakes_cache import migrate as run_brakes_cache_migration
from migrations.add_description_aliases import migrate as run_description_aliases_migration
from migrations.add_brakes_dietary_info import migrate as run_brakes_dietary_info_migration
from migrations.add_ingredient_flag_dismissals import migrate as run_ingredient_flag_dismissals_migration
from migrations.add_menus import migrate as run_menus_migration
from migrations.add_ingredient_is_free import migrate as run_ingredient_is_free_migration
from migrations.add_recipe_text_flag_dismissals import migrate as run_recipe_text_flag_dismissals_migration
from migrations.add_llm_infrastructure import migrate as run_llm_infrastructure_migration
from migrations.add_changelog_invoice_link import migrate as run_changelog_invoice_link_migration
from migrations.add_sambapos_portion_name import migrate as run_sambapos_portion_name_migration

from scheduler import start_scheduler, stop_scheduler

logger = logging.getLogger(__name__)


async def _run(name, coro):
    try:
        await coro()
        logger.info(f"{name} migration completed")
    except Exception as e:
        logger.warning(f"{name} migration warning (may be expected): {e}")


@asynccontextmanager
async def lifespan(app: FastAPI):
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    await _run("Invoice features", run_migration)
    await _run("Newbook tables", run_newbook_migration)
    await _run("Line item search", run_search_migration)
    await _run("SambaPOS settings", run_sambapos_migration)
    await _run("SambaPOS excluded items", run_sambapos_excluded_migration)
    await _run("Admin restricted pages", run_admin_pages_migration)
    await _run("Nextcloud backup", run_nextcloud_backup_migration)
    await _run("Price settings", run_price_settings_migration)
    await _run("Resos integration", run_resos_migration)
    await _run("Calendar events", run_calendar_events_migration)
    await _run("Resos upcoming sync", run_resos_upcoming_sync_migration)
    await _run("Newbook upcoming sync", run_newbook_upcoming_sync_migration)
    await _run("Residents table chart", run_residents_table_chart_migration)
    await _run("Rooms breakdown", run_rooms_breakdown_migration)
    await _run("Invoice disputes", run_disputes_migration)
    await _run("Awaiting replacement status", run_awaiting_replacement_migration)
    await _run("NEW status", run_new_status_migration)
    await _run("Dispute attachment public hash", run_dispute_attachment_hash_migration)
    await _run("Logbook", run_logbook_migration)
    await _run("IMAP integration", run_imap_migration)
    await _run("Support request", run_support_migration)
    await _run("PDF annotation settings", run_pdf_annotation_settings_migration)
    await _run("Linked dispute", run_linked_dispute_migration)
    await _run("OCR post-processing", run_ocr_post_processing_migration)
    await _run("OCR weight setting", run_ocr_weight_setting_migration)
    await _run("Budget settings", run_budget_settings_migration)
    await _run("Cover overrides", run_cover_overrides_migration)
    await _run("Purchase orders", run_purchase_orders_migration)
    await _run("Supplier PO fields", run_supplier_po_fields_migration)
    await _run("Kitchen details", run_kitchen_details_migration)
    await _run("Cost distributions", run_cost_distributions_migration)
    await _run("Recipe system", run_recipe_system_migration)
    await _run("Flag assessment", run_flag_assessment_migration)
    await _run("Dish separation", run_dish_separation_migration)
    await _run("Step title", run_step_title_migration)
    await _run("Gross sell price", run_gross_sell_price_migration)
    await _run("Recipe ingredient yield", run_recipe_ingredient_yield_migration)
    await _run("Recipe batch type", run_recipe_batch_type_migration)
    await _run("Sub-recipe unit", run_sub_recipe_unit_migration)
    await _run("Recipe ingredient unit", run_recipe_ingredient_unit_migration)
    await _run("Allergen keywords", run_allergen_keywords_migration)
    await _run("Brakes product cache", run_brakes_cache_migration)
    await _run("Description aliases", run_description_aliases_migration)
    await _run("Brakes dietary info", run_brakes_dietary_info_migration)
    await _run("Ingredient flag dismissals", run_ingredient_flag_dismissals_migration)
    await _run("Menus", run_menus_migration)
    await _run("Ingredient is_free", run_ingredient_is_free_migration)
    await _run("Recipe text flag dismissals", run_recipe_text_flag_dismissals_migration)
    await _run("LLM infrastructure", run_llm_infrastructure_migration)
    await _run("Changelog invoice link", run_changelog_invoice_link_migration)
    await _run("SambaPOS portion name", run_sambapos_portion_name_migration)

    start_scheduler()

    yield

    stop_scheduler()
    await engine.dispose()


app = FastAPI(
    title="Kitchen App",
    description="Invoice/GP, recipes, menus — Hotel Number Four kitchen management",
    version="1.0.0",
    lifespan=lifespan,
)

# No CORS middleware — same-origin via nginx (A1)

app.include_router(invoices.router, prefix="/api/invoices", tags=["Invoices"])
app.include_router(disputes.router, prefix="/api/disputes", tags=["Disputes"])
app.include_router(credit_notes.router, prefix="/api/credit-notes", tags=["Credit Notes"])
app.include_router(suppliers.router, prefix="/api/suppliers", tags=["Suppliers"])
app.include_router(reports.router, prefix="/api/reports", tags=["Reports"])
app.include_router(reconciliation.router, prefix="/api/reports", tags=["Reconciliation"])
app.include_router(settings.router, prefix="/api/settings", tags=["Settings"])
app.include_router(field_mappings.router, prefix="/api/field-mappings", tags=["Field Mappings"])
app.include_router(newbook.router, prefix="/api/newbook", tags=["Newbook"])
app.include_router(sambapos.router, prefix="/api/sambapos", tags=["SambaPOS"])
app.include_router(backup.router, prefix="/api/backup", tags=["Backup"])
app.include_router(search.router, tags=["Search"])
app.include_router(resos.router, prefix="/api/resos", tags=["Resos"])
app.include_router(calendar_events.router, prefix="/api/calendar-events", tags=["Calendar Events"])
app.include_router(residents_table_chart.router, prefix="/api", tags=["Residents Table Chart"])
app.include_router(public.router, prefix="/api/public", tags=["Public"])
app.include_router(logbook.router, prefix="/api", tags=["Logbook"])
app.include_router(imap.router, prefix="/api", tags=["IMAP"])
app.include_router(support.router, prefix="/api", tags=["Support"])
app.include_router(budget.router, prefix="/api/budget", tags=["Budget"])
app.include_router(cover_overrides.router, prefix="/api/cover-overrides", tags=["Cover Overrides"])
app.include_router(purchase_orders.router, prefix="/api/purchase-orders", tags=["Purchase Orders"])
app.include_router(cost_distributions.router, prefix="/api/cost-distributions", tags=["Cost Distributions"])
app.include_router(ingredients.router, prefix="/api/ingredients", tags=["Ingredients"])
app.include_router(recipes.router, prefix="/api/recipes", tags=["Recipes"])
app.include_router(food_flags.router, prefix="/api/food-flags", tags=["Food Flags"])
app.include_router(event_orders.router, prefix="/api/event-orders", tags=["Event Orders"])
app.include_router(menus.router, prefix="/api/menus", tags=["Menus"])
app.include_router(external.router, prefix="/api/external", tags=["External API"])
app.include_router(internal_router)


@app.get("/health")
async def health_check():
    return {"status": "healthy"}
