"""
FiHotelFlow - Hotel Management System
Main FastAPI application entry point.
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session

from app.config import settings
from app.database import engine, Base, SessionLocal
from app.api.router import api_router
from app.models.user import User, UserRole
from app.models.department import Department, DepartmentCategory
from app.models.stats import TaxRate
from app.models.establishment import Establishment
from app.models.permission import RolePermission, UserPermissionOverride  # noqa: F401 - ensures tables are created
from app.models.billing import Invoice, InvoiceItem, Receipt  # noqa: F401 - ensures tables are created
from app.core.security import get_password_hash
from app.seeds.budget_seeds import seed_budgets
from app.seeds.hotel_seeds import seed_hotel_data


def create_default_data(db: Session):
    """Create default data if not exists."""
    # Create default establishment
    establishment = db.query(Establishment).first()
    if not establishment:
        establishment = Establishment(
            name="Hôtel FiHotelFlow",
            address="123 Avenue de l'Hôtel",
            city="Dakar",
            country="Sénégal",
            postal_code="10000",
            phone="+221 33 800 00 00",
            email="contact@fihotelflow.com",
            capacity_rooms=50,
            capacity_beds=100,
            currency="XOF",
            default_checkin_time="14:00",
            default_checkout_time="12:00"
        )
        db.add(establishment)
        db.commit()
        db.refresh(establishment)
        print(f"Created default establishment: {establishment.name}")

    # Create default admin user
    admin = db.query(User).filter(User.email == settings.default_admin_email).first()
    if not admin:
        admin = User(
            email=settings.default_admin_email,
            hashed_password=get_password_hash(settings.default_admin_password),
            first_name="Admin",
            last_name="System",
            role=UserRole.ADMIN,
            is_active=True
        )
        db.add(admin)
        print(f"Created default admin user: {settings.default_admin_email}")

    # Create default departments
    default_departments = [
        ("HEBERG", "Hébergement", "Accommodation", DepartmentCategory.ACCOMMODATION),
        ("REST", "Restaurant", "Restaurant", DepartmentCategory.FOOD_BEVERAGE),
        ("BAR", "Bar", "Bar", DepartmentCategory.FOOD_BEVERAGE),
        ("ROOM_SERVICE", "Room Service", "Room Service", DepartmentCategory.FOOD_BEVERAGE),
        ("SPA", "Spa & Wellness", "Spa & Wellness", DepartmentCategory.OTHER_REVENUE),
        ("BOUTIQUE", "Boutique", "Shop", DepartmentCategory.BOUTIQUE),
        ("PARKING", "Parking", "Parking", DepartmentCategory.OTHER_REVENUE),
        ("LAUNDRY", "Blanchisserie", "Laundry", DepartmentCategory.OTHER_REVENUE),
        ("MINIBAR", "Minibar", "Minibar", DepartmentCategory.FOOD_BEVERAGE),
        ("PHONE", "Téléphone", "Telephone", DepartmentCategory.OTHER_REVENUE),
        ("MISC", "Divers", "Miscellaneous", DepartmentCategory.OTHER_REVENUE),
    ]

    for code, name, name_en, category in default_departments:
        dept = db.query(Department).filter(Department.code == code).first()
        if not dept:
            dept = Department(
                code=code,
                name=name,
                name_en=name_en,
                category=category,
                is_revenue=True,
                is_active=True
            )
            db.add(dept)

    # Create default tax rates
    default_taxes = [
        ("TVA_20", "TVA 20%", "VAT 20%", 20.0, False),
        ("TVA_10", "TVA 10%", "VAT 10%", 10.0, True),
        ("TVA_5.5", "TVA 5.5%", "VAT 5.5%", 5.5, False),
        ("TVA_0", "Exonéré", "Tax Exempt", 0.0, False),
    ]

    for code, name, name_en, rate, is_default in default_taxes:
        tax = db.query(TaxRate).filter(TaxRate.code == code).first()
        if not tax:
            tax = TaxRate(
                code=code,
                name=name,
                name_en=name_en,
                rate=rate,
                is_default=is_default,
                is_active=True
            )
            db.add(tax)

    db.commit()

    # Seed budget data for comparative analysis
    seed_budgets(db)

    # Seed hotel operational data (rooms, clients, reservations, folios)
    seed_hotel_data(db)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan events."""
    # Startup
    print(f"Starting {settings.app_name} v{settings.app_version}")

    # Create tables
    Base.metadata.create_all(bind=engine)
    print("Database tables created/verified")

    # Create default data
    db = SessionLocal()
    try:
        create_default_data(db)
        print("Default data initialized")
    finally:
        db.close()

    yield

    # Shutdown
    print(f"Shutting down {settings.app_name}")


# Create FastAPI application
app = FastAPI(
    title=settings.app_name,
    description="Hotel Management System API - Gestion hôtelière complète",
    version=settings.app_version,
    lifespan=lifespan,
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json"
)

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

# Include API router
app.include_router(api_router, prefix="/api")


@app.get("/")
def root():
    """Root endpoint - API information."""
    return {
        "name": settings.app_name,
        "version": settings.app_version,
        "description": "Hotel Management System API",
        "docs": "/docs",
        "health": "/health"
    }


@app.get("/health")
def health_check():
    """Health check endpoint."""
    return {
        "status": "healthy",
        "version": settings.app_version
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "app.main:app",
        host="0.0.0.0",
        port=8000,
        reload=settings.debug
    )
