import os
import time
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware

from model.action_log_model import ActionLogModel
from utils.auth_helper import get_current_actor_optional
from utils.audit_helper import parse_request_body, outcome_from_status

# --- 1. Import Controllers ---
from controller.admin.product_controller import router as product_router
from controller.admin.upload_controller import router as upload_router
from controller.admin.category_controller import router as category_admin_router
from controller.public.category_controller import router as category_public_router
from controller.public.product_controller import router as product_public_router
from controller.topup_controller import router as topup_router
from controller import ticket_controller
from controller.staff_controller import router as staff_router
from controller.banner import router as banner_router
from controller.import_controller import router as import_router
from controller.order_controller import router as order_controller
from controller.product_catalog_controller import router as product_catalog_router
from controller.action_log_controller import router as action_log_router
from controller.upload_public_controller import router as upload_public_router

# Import 2 Controller phân quyền mới
from controller import user_controller, admin_controller

app = FastAPI(title="Ecommerce API", root_path="/pod-api")

app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=["*"])

WRITE_METHODS = {"POST", "PUT", "DELETE", "PATCH"}
ALLOWED_LOG_ROLES = {"admin", "staff"}


@app.middleware("http")
async def action_log_middleware(request: Request, call_next):
    if request.method not in WRITE_METHODS:
        return await call_next(request)

    start_time = time.time()

    # Đọc body trước để log, rồi nạp lại cho downstream dùng tiếp
    body = await request.body()
    content_type = request.headers.get("content-type", "")

    async def receive():
        return {
            "type": "http.request",
            "body": body,
            "more_body": False
        }

    request = Request(request.scope, receive)

    actor = await get_current_actor_optional(request)

    status_code = 500

    try:
        response = await call_next(request)
        status_code = response.status_code
        return response
    finally:
        duration_ms = int((time.time() - start_time) * 1000)
        required_permission = getattr(request.state, "required_permission", None)
        final_actor = getattr(request.state, "actor", actor)

        # Chỉ log admin / staff. User hoặc Unknown thì bỏ qua.
        should_log = (
            final_actor
            and str(final_actor.get("role", "")).lower() in ALLOWED_LOG_ROLES
            and str(final_actor.get("id", "")).strip() != ""
        )

        if should_log:
            try:
                ActionLogModel.write_log({
                    "method": request.method,
                    "path": request.url.path,
                    "query": str(request.url.query),
                    "statusCode": status_code,
                    "allowed": status_code not in [401, 403],
                    "success": 200 <= status_code < 300,
                    "outcome": outcome_from_status(status_code),
                    "requiredPermission": required_permission,
                    "actorId": final_actor.get("id"),
                    "actorName": final_actor.get("name"),
                    "actorRole": final_actor.get("role"),
                    "ip": request.client.host if request.client else None,
                    "userAgent": request.headers.get("user-agent"),
                    "durationMs": duration_ms,
                    "body": parse_request_body(content_type, body)
                })
            except Exception as log_error:
                print(f"[ACTION LOG ERROR] {log_error}")


# --- 2. Cấu hình CORS ---
origins = [
    "http://103.90.225.225",
    "http://05factory.com",
    "https://05factory.com",
    "http://www.05factory.com",
    "https://www.05factory.com",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# --- 3. Gắn Router ---
app.include_router(staff_router, prefix="/api", tags=["Admin Staff Management"])
app.include_router(product_router, prefix="/api/admin", tags=["Admin Product"])
app.include_router(upload_router, prefix="/api/admin", tags=["Admin Upload"])
app.include_router(category_admin_router, prefix="/api/admin", tags=["Admin Category"])
app.include_router(action_log_router, prefix="/api")

app.include_router(category_public_router, prefix="/api", tags=["Public Catalog"])
app.include_router(product_public_router, prefix="/api", tags=["Public Product"])
app.include_router(topup_router, prefix="/api/topups", tags=["Top-up"])
app.include_router(ticket_controller.router, prefix="/api/tickets", tags=["Tickets"])
app.include_router(banner_router, prefix="/api", tags=["Banner"])
app.include_router(import_router, prefix="/api/import", tags=["Import Orders"])
app.include_router(order_controller, prefix="/api/orders", tags=["Orders"])
app.include_router(product_catalog_router, prefix="/api", tags=["Product Catalog"])

app.include_router(user_controller.router, prefix="/api")
app.include_router(admin_controller.router, prefix="/api")

app.include_router(upload_public_router, prefix="/api", tags=["Public Upload"])

# --- 4. Static Files ---
base_dir = os.path.dirname(os.path.abspath(__file__))
upload_path = os.path.join(base_dir, "uploads")

if not os.path.exists(upload_path):
    os.makedirs(upload_path)

app.mount("/uploads", StaticFiles(directory=upload_path), name="uploads")