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.middleware.base import BaseHTTPMiddleware
from starlette.exceptions import HTTPException as StarletteHTTPException
from app.scheduler import start_scheduler

import firebase_admin
from firebase_admin import credentials, messaging


# 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)

try:
    cred = credentials.Certificate("firebase-key.json")
    firebase_admin.initialize_app(cred)
    print("✅ Firebase initialized for FCM notifications")
except Exception as e:
    print(f"⚠️ Firebase initialization failed: {e}")

# Importing routers from the v1/routers/saas directory for the SaaS application features
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, activity, communication_email
)
from app.v1.routers.cx import crm, comm, ticket
from app.v1.routers import crud
# Importing routers from the v1/routers/dependencies directory for the Auth features
from app.v1.dependencies import (
    auth
)
# Importing routers from the v1/routers directory for the main application features
from app.v1.routers.platform import (
    booking, customers, marketplace
)

# 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,
    websocket_workforce_schedules,
    websocket_nearby_devices,
    websocket_historical_and_live,
    websocket_historical_and_live_all
)
from app.v1.consumers.kafka_consumer import consume_tracking_data
from aiokafka.errors import KafkaConnectionError

app = FastAPI()

# CORS setup
# origins = [
#     "http://localhost:3000",
#     "http://localhost:3001",
#     "https://www.movex.ai",
#     "http://beta.movex.ai",
#     "https://beta.movex.ai",
#     "https://staging.movex.ai",
# ]

origins = [
    "http://localhost:3000",
    "http://localhost:3001",
    "https://www.movex.ai",
    "http://beta.movex.ai",
    "https://beta.movex.ai",
    "https://staging.movex.ai",
    "*"   # ✅ allows mobile apps & Postman
]

app.add_middleware(auth.AuthMiddleware)
# app.add_middleware(
#     CORSMiddleware,
#     allow_origins=origins,
#     allow_credentials=True,
#     allow_methods=["*"],
#     allow_headers=["*"],
# )
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.add_middleware(InputSanitizationMiddleware)

# Create a separate router for endpoints with CORS set to "*"
open_cors_router = FastAPI()

# Apply CORS middleware to this specific router
open_cors_router.add_middleware(
    CORSMiddleware,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.exception_handler(StarletteHTTPException)

#public access
app.mount("/public", StaticFiles(directory="public"), name="public")

# User and Authentication
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"])

# Main application features
app.include_router(dashboard.router, prefix="/v1/dashboard", tags=["Dashboard"])
#app.include_router(saas.router, prefix="/v1/saas", tags=["subscriptions "])
#app.include_router(support.router, prefix="/v1/support", tags=["Support "])

app.include_router(subscriptions.router, prefix="/v1/saas", tags=["subscription-types"])
app.include_router(subscriptions.router, prefix="/v1/saas/subscribe", tags=["subscribe"])

app.include_router(subscriptions.router, prefix="/v1/subscriptions", tags=["Subscriptions"])
app.include_router(invoices.router, prefix="/v1/invoices", 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/emails", tags=["Communication Email"])

app.include_router(crud.router, prefix="/v1/crud", tags=["crud"])
app.include_router(ticket.router, prefix="/v1/ticket", tags=["Ticket"])
#app.include_router(comm.router, prefix="/v1/cx/ticket", tags=["Communication Channels"])

#Platform routers
#app.include_router(booking.router, prefix="/v1/booking", tags=["Booking"])

# 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(iotdevices.router, prefix="/v1/withmapping", tags=["withmapping"])
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"])

#schedular for payment reminder


# WebSocket: tracking ingestion endpoint
@app.websocket("/ws/tracking_data")
async def tracking_data_socket(websocket: WebSocket):
    print("🔥 tracking_data_socket called BEFORE accept")
    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)

@app.websocket("/ws/historical_and_live")
async def historical_and_live_socket(websocket: WebSocket):
    await websocket_historical_and_live(websocket)

#Return all the historical data in single api call
@app.websocket("/ws/historical_and_live_all")
async def historical_and_live_all_socket(websocket: WebSocket):
    await websocket_historical_and_live_all(websocket)

@app.websocket("/ws/workforceschedule-updates")
async def realtime_updates(websocket: WebSocket):
    await websocket_workforce_schedules(websocket)

@app.websocket("/ws/nearby-devices")
async def nearby_devices_socket(websocket: WebSocket):
    await websocket_nearby_devices(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("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)

    # 🔹 Start APScheduler
    start_scheduler()
    print("✅ APScheduler started")


@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"]

# Custom middleware to restrict access
@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")
    response = await call_next(request)
    return response
