import path from "path";
import express from "express";
import cors from "cors";
import helmet from "helmet";
import rateLimit from "express-rate-limit";
import { env } from "@/config/env";
import { errorHandler } from "@/lib/errors";
import { authRouter } from "@/routes/auth";
import { citiesRouter } from "@/routes/cities";
import { propertiesRouter } from "@/routes/properties";
import { bookingsRouter } from "@/routes/bookings";
import { favoritesRouter } from "@/routes/favorites";
import { reviewsRouter } from "@/routes/reviews";
import { notificationsRouter } from "@/routes/notifications";
import { adminRouter } from "@/routes/admin";
import { dashboardRouter } from "@/routes/dashboard";
import { contactRouter } from "@/routes/contact";
import { uploadsRouter } from "@/routes/uploads";
import { walletRouter } from "@/routes/wallet";
import { loyaltyRouter } from "@/routes/loyalty";

/** Private LAN origins for phone-on-WiFi testing (development only). */
function isPrivateLanOrigin(origin: string) {
  try {
    const { hostname } = new URL(origin);
    if (hostname === "localhost" || hostname === "127.0.0.1") return true;
    const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
    if (!m) return false;
    const a = Number(m[1]);
    const b = Number(m[2]);
    if (a === 10) return true;
    if (a === 192 && b === 168) return true;
    if (a === 172 && b >= 16 && b <= 31) return true;
    return false;
  } catch {
    return false;
  }
}

function corsOriginDelegate(
  origin: string | undefined,
  callback: (err: Error | null, allow?: boolean) => void,
) {
  const allowed = env.CORS_ORIGIN.split(",")
    .map((s) => s.trim())
    .filter(Boolean);

  // Non-browser / same-origin tools
  if (!origin) {
    callback(null, true);
    return;
  }

  if (allowed.includes(origin)) {
    callback(null, true);
    return;
  }

  // Dev / local: allow phone/tablet on the same private Wi‑Fi
  // (tsx often runs without NODE_ENV=development)
  if (env.NODE_ENV !== "production" && isPrivateLanOrigin(origin)) {
    callback(null, true);
    return;
  }

  // Reject without throwing — throwing yields HTTP 500 to API clients
  callback(null, false);
}

export function createApp() {
  const app = express();

  app.use(
    helmet({
      crossOriginResourcePolicy: { policy: "cross-origin" },
    }),
  );
  app.use(
    cors({
      origin: corsOriginDelegate,
      credentials: true,
    }),
  );
  app.use(express.json({ limit: "1mb" }));
  app.use("/images", express.static(path.join(process.cwd(), "public", "images")));
  app.use("/uploads", express.static(path.join(process.cwd(), "public", "uploads")));

  app.use(
    "/api/auth",
    rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 100,
      standardHeaders: true,
      legacyHeaders: false,
    }),
  );

  // Sensitive money / mutation routes — tighter than public browsing
  const moneyLimiter = rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 60,
    standardHeaders: true,
    legacyHeaders: false,
  });
  app.use("/api/bookings", moneyLimiter);
  app.use("/api/wallet", moneyLimiter);
  app.use("/api/dashboard/owner/withdraw", moneyLimiter);

  app.get("/health", (_req, res) => res.json({ ok: true, service: "safar-libya-api" }));

  app.use("/api/auth", authRouter);
  app.use("/api/cities", citiesRouter);
  app.use("/api/search/cities", citiesRouter);
  app.use("/api/properties", propertiesRouter);
  app.use("/api/bookings", bookingsRouter);
  app.use("/api/favorites", favoritesRouter);
  app.use("/api/reviews", reviewsRouter);
  app.use("/api/notifications", notificationsRouter);
  app.use("/api/wallet", walletRouter);
  app.use("/api/loyalty", loyaltyRouter);
  app.use("/api/admin", adminRouter);
  app.use("/api/dashboard", dashboardRouter);
  app.use("/api/contact", contactRouter);
  app.use("/api/uploads", uploadsRouter);

  app.use(errorHandler);
  return app;
}
