import asyncio
from fastapi import FastAPI, Request, HTTPException, WebSocket
from fastapi.responses import RedirectResponse
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
from app.middleware import InputSanitizationMiddleware
from fastapi.staticfiles import StaticFiles
from starlette.exceptions import HTTPException as StarletteHTTPException

# Load environment variables
if not load_dotenv():
    print("Could not load .env file or it is empty. Please check if it exists and is readable.")
    exit(1)

# Platform & SaaS routers
from app.v1.routers.platform import (
    booking, customers, marketplace, services, workforce, workforcecategory,
    pricingrules, vehicles, fleets, vendors, workforcevehicle, workforcetimesheet,
    customer_accounts, tasks, schedules, payment, availability, applinks, ui,
    monitoring, communication, iotdevices, geofences, geofencerules,
    geofence_rule_mapping, integrations, language_regional, account_settings, subscription
)
from app.v1.routers.saas import (
    accounts, subscriptions, support, supportcustomer, users, roles,
    login, dashboard, audit, rbac, appflow, partners, common, invoices, tickets, activity, communication_email
)
from app.v1.routers.cx import crm, comm, ticket
from app.v1.routers import crud
from app.v1.dependencies import auth

# Kafka and WebSocket logic
from app.v1.sockets.tracking_data import (
    websocket_tracking_data,
    websocket_realtime_updates,
    start_kafka_producer,
    stop_kafka_producer,
    websocket_historical_route
)
from app.v1.consumers.kafka_consumer import consume_tracking_data
from aiokafka.errors import KafkaConnectionError

app = FastAPI()

# CORS setup
origins = [
    "http://localhost:3000",
    "https://www.movex.ai",
]

app.add_middleware(auth.AuthMiddleware)
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.add_middleware(InputSanitizationMiddleware)

# Static Public Assets
app.mount("/public", StaticFiles(directory="public"), name="public")

# SaaS & User modules
app.include_router(accounts.router, prefix="/v1/accounts", tags=["Accounts"])
app.include_router(login.router, prefix="/v1/auth", tags=["Login"])
app.include_router(users.router, prefix="/v1/users", tags=["Users"])
app.include_router(roles.router, prefix="/v1/roles", tags=["Roles"])
app.include_router(rbac.router, prefix="/v1/rbac", tags=["RBAC"])
app.include_router(common.router, prefix="/v1/common", tags=["RBAC"])
app.include_router(appflow.router, prefix="/v1/appflow", tags=["Apps"])
app.include_router(partners.router, prefix="/v1/partners", tags=["Partners"])
app.include_router(audit.router, prefix="/v1/audit", tags=["Audit"])
app.include_router(dashboard.router, prefix="/v1/dashboard", tags=["Dashboard"])
app.include_router(subscriptions.router, prefix="/v1/subscriptions", tags=["Subscriptions"])
app.include_router(invoices.router, prefix="/v1/saasinvoices", tags=["SaaS Invoices"])
app.include_router(support.router, prefix="/v1/support", tags=["Support"])
app.include_router(supportcustomer.router, prefix="/v1/supportcustomer", tags=["Customer Support"])
app.include_router(crm.router, prefix="/v1/cx/crm", tags=["CRM"])
app.include_router(crud.router, prefix="/v1/crud", tags=["CRUD"])
app.include_router(tickets.router, prefix="/v1/tickets", tags=["Tickets"])
app.include_router(activity.router, prefix="/v1/activity", tags=["Activity"])
app.include_router(communication_email.router, prefix="/v1/communication_email", tags=["Communication Email"])

# Platform modules
app.include_router(services.router, prefix="/v1/services", tags=["Services"])
app.include_router(workforce.router, prefix="/v1/workforce", tags=["Workforce"])
app.include_router(workforcecategory.router, prefix="/v1/workforcecategory", tags=["Workforce Category"])
app.include_router(vehicles.router, prefix="/v1/vehicle-models", tags=["Vehicles"])
app.include_router(fleets.router, prefix="/v1/fleets", tags=["Fleets"])
app.include_router(vendors.router, prefix="/v1/vendors", tags=["Vendors"])
app.include_router(workforcevehicle.router, prefix="/v1/workforcevehicle", tags=["Workforce Vehicle"])
app.include_router(workforcetimesheet.router, prefix="/v1/workforcetimesheet", tags=["Workforce Timesheet"])
app.include_router(customers.router, prefix="/v1/customers", tags=["Customers"])
app.include_router(customer_accounts.router, prefix="/v1/customer_accounts", tags=["Customer Accounts"])
app.include_router(tasks.router, prefix="/v1/tasks", tags=["Tasks"])
app.include_router(schedules.router, prefix="/v1/schedules", tags=["Schedules"])
app.include_router(pricingrules.router, prefix="/v1/pricingrules", tags=["Pricing Rules"])
app.include_router(availability.router, prefix="/v1/availability", tags=["Availability"])
app.include_router(communication.router, prefix="/v1/communication", tags=["Communication"])
app.include_router(payment.router, prefix="/v1/payment", tags=["Payment"])
app.include_router(applinks.router, prefix="/v1/applinks", tags=["App Links"])
app.include_router(ui.router, prefix="/v1/ui", tags=["UI"])
app.include_router(monitoring.router, prefix="/v1/monitoring", tags=["Monitoring"])
app.include_router(integrations.router, prefix="/v1/integrations", tags=["Integrations"])
app.include_router(language_regional.router, prefix="/v1/language_regional", tags=["Language & Regional"])
app.include_router(account_settings.router, prefix="/v1/account_settings", tags=["Account Settings"])
app.include_router(subscription.router, prefix="/v1/subscription", tags=["Subscription"])
app.include_router(iotdevices.router, prefix="/v1/iotdevices", tags=["IoT Devices"])
app.include_router(geofences.router, prefix="/v1/geofences", tags=["Geofences"])
app.include_router(geofencerules.router, prefix="/v1/geofencerules", tags=["Geofence Rules"])
app.include_router(geofence_rule_mapping.router, prefix="/v1/geofence_rule_mapping", tags=["Geofence Rule Mapping"])

# WebSocket: tracking ingestion endpoint
@app.websocket("/ws/tracking_data")
async def tracking_data_socket(websocket: WebSocket):
    await websocket_tracking_data(websocket)

# WebSocket: real-time broadcast to connected clients
@app.websocket("/ws/realtime")
async def realtime_updates_socket(websocket: WebSocket):
    await websocket_realtime_updates(websocket)

@app.websocket("/ws/historical_route")
async def historical_route_socket(websocket: WebSocket):
    await websocket_historical_route(websocket)

# Kafka startup/shutdown
@app.on_event("startup")
async def startup_event():
    try:
        await start_kafka_producer()
        asyncio.create_task(consume_tracking_data())
    except KafkaConnectionError as e:
        print("Kafka not available, skipping producer start:", e)

@app.on_event("shutdown")
async def shutdown_event():
    await stop_kafka_producer()

# Restrict access to Swagger UI by IP
allowed_ips = ["127.0.0.1"]

@app.middleware("http")
async def restrict_access(request: Request, call_next):
    client_ip = request.client.host
    if request.url.path.startswith("/docs") or request.url.path.startswith("/redoc"):
        if client_ip not in allowed_ips:
            raise HTTPException(status_code=404, detail="Forbidden")
    return await call_next(request)
