import asyncio
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import RedirectResponse
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
from app.middleware import InputSanitizationMiddleware  # Import the middleware from the module
from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.exceptions import HTTPException as StarletteHTTPException

#from app.api.v1.dependencies.auth import AuthMiddleware  # Import the middleware
#gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --certfile=cert.pem --keyfile=key.pem

if not load_dotenv():
    print("Could not load .env file or it is empty. Please check if it exists and is readable.")
    exit(1)

# Importing routers from the v1/routers/saas directory for the SaaS application features
from app.v1.routers.saas import (
    accounts, subscriptions , support, supportcustomer, users, roles, 
    login, dashboard, audit, rbac, appflow, partners, common,
    invoices
)
from app.v1.routers import crud

from app.v1.routers.cx import (
    crm, comm, ticket
)
# 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, 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
)

#Socket
#from app.v1.sockets import tracking_data as tracking_data_socket
from fastapi import WebSocket

# Kafka lifecycle
from app.v1.sockets.tracking_data import websocket_endpoint, start_kafka_producer, stop_kafka_producer
from app.v1.consumers.kafka_consumer import consume_tracking_data
from aiokafka.errors import KafkaConnectionError


app = FastAPI()

origins = [
    "http://localhost:3000",
    "https://www.movex.ai",

]
app.add_middleware(auth.AuthMiddleware)
app.add_middleware(
    CORSMiddleware,
    #allow_origins=["*"], 
    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"])
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(ticket.router, prefix="/v1/cx/comm", tags=["Ticketing"])
#app.include_router(comm.router, prefix="/v1/cx/ticket", tags=["Communication Channels"])

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=["Workforcecategory"])
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(services.router, prefix="/v1/services", tags=["Services"])
app.include_router(workforcevehicle.router, prefix="/v1/workforcevehicle", tags=["Workforce Vehicle"])
app.include_router(workforcetimesheet.router, prefix="/v1/workforcetimesheet", tags=["Workforce Timesheet"])

#Coustomer
app.include_router(customers.router, prefix="/v1/customers", tags=["Customers"])
app.include_router(customer_accounts.router, prefix="/v1/customer_accounts", tags=["Customer Accounts"])

#Tasks
app.include_router(tasks.router, prefix="/v1/tasks", tags=["Tasks"])

#Schedules
app.include_router(schedules.router, prefix="/v1/schedules", tags=["Schedules"])

#Pricing Rules Routers
app.include_router(pricingrules.router, prefix="/v1/pricingrules", tags=["Pricingrules"])

#Settings
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=["Applinks"])
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"])

#iotdevices
app.include_router(iotdevices.router, prefix="/v1/iotdevices", tags=["Iot Devices"])

#geofences
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"])

#Socket For Track Location
#app.include_router(tracking_data_socket.router, tags=["Tracking WebSocket"])
#app.include_router(tracking_data_socket.router, tags=["Tracking WebSocket"]) This one working perfect normal flow
#app.include_router(tracking_data_socket.router, prefix="/v1/tracking_data_socket", tags=["Tracking WebSocket"])

@app.websocket("/ws/tracking_data")
async def socket_handler(websocket: WebSocket):
    await websocket_endpoint(websocket)

@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()


#Platform routers
#app.include_router(booking.router, prefix="/v1/booking", tags=["Booking"])

# Integrations

# 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 "])


# Define a list of allowed IP addresses
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

