import type { ActionFunctionArgs, LoaderFunctionArgs } from "react-router";
import * as path from "path";
import * as fs from "fs";
import { getTenantByDomain } from "../lib/security/tenant-context";
import { checkRateLimit } from "../lib/security/rate-limit";
import { logger } from "../lib/security/logger";
import { getDefaultStoreDomainSync } from "../services/platform-settings.server";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
  "Access-Control-Allow-Headers": "*, Content-Type, Authorization, X-Requested-With, Cache-Control, Pragma, Accept, Origin",
  "Access-Control-Max-Age": "86400",
  "Content-Type": "application/json",
  "Cache-Control": "no-cache, no-store, must-revalidate",
};

const ALLOWED_MIME_TYPES = new Set([
  "image/jpeg",
  "image/jpg",
  "image/png",
  "image/webp",
  "image/gif",
]);

const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB

export const loader = async ({ request }: LoaderFunctionArgs) => {
  if (request.method === "OPTIONS") {
    return new Response(null, { status: 204, headers: corsHeaders });
  }
  return new Response(JSON.stringify({ status: "Upload endpoint active" }), { headers: corsHeaders });
};

export const action = async ({ request }: ActionFunctionArgs) => {
  if (request.method === "OPTIONS") {
    return new Response(null, { status: 204, headers: corsHeaders });
  }

  try {
    const url = new URL(request.url);
    const queryShop = url.searchParams.get("shop");
    const contentType = request.headers.get("content-type") || "";

    // Rate Limit: 20 uploads / min
    const shop = (queryShop || getDefaultStoreDomainSync()).toLowerCase().trim();
    checkRateLimit({ key: `upload_${shop}`, maxTokens: 20, refillIntervalMs: 60000 });

    const uploadsDir = path.resolve(process.cwd(), "uploads");
    if (!fs.existsSync(uploadsDir)) {
      fs.mkdirSync(uploadsDir, { recursive: true });
    }

    let fileBuffer: Buffer | null = null;
    let mimeType = "image/jpeg";
    let originalName = "upload.jpg";

    if (contentType.includes("multipart/form-data")) {
      const formData = await request.formData();
      const file = formData.get("file") as File | null;
      if (!file || typeof file === "string") {
        return new Response(
          JSON.stringify({ success: false, error: "No image file provided in form data" }),
          { status: 400, headers: corsHeaders }
        );
      }

      if (!ALLOWED_MIME_TYPES.has(file.type)) {
        return new Response(
          JSON.stringify({ success: false, error: "Invalid file type. Only JPEG, PNG, WebP, and GIF images are allowed." }),
          { status: 400, headers: corsHeaders }
        );
      }

      if (file.size > MAX_FILE_SIZE) {
        return new Response(
          JSON.stringify({ success: false, error: "File exceeds 5MB size limit." }),
          { status: 400, headers: corsHeaders }
        );
      }

      mimeType = file.type;
      originalName = file.name || "upload.jpg";
      const arrayBuffer = await file.arrayBuffer();
      fileBuffer = Buffer.from(arrayBuffer);
    } else {
      // JSON body with base64 data
      const json = await request.json().catch(() => ({}));
      const { image, filename } = json;

      if (!image || typeof image !== "string") {
        return new Response(
          JSON.stringify({ success: false, error: "No image payload provided" }),
          { status: 400, headers: corsHeaders }
        );
      }

      const match = image.match(/^data:(image\/[a-zA-Z0-9.+_-]+);base64,(.+)$/);
      if (match) {
        mimeType = match[1];
        const base64Data = match[2];
        fileBuffer = Buffer.from(base64Data, "base64");
      } else {
        fileBuffer = Buffer.from(image, "base64");
      }

      if (filename) originalName = filename;
    }

    if (!fileBuffer || fileBuffer.length === 0) {
      return new Response(
        JSON.stringify({ success: false, error: "Empty image buffer received" }),
        { status: 400, headers: corsHeaders }
      );
    }

    if (fileBuffer.length > MAX_FILE_SIZE) {
      return new Response(
        JSON.stringify({ success: false, error: "File exceeds 5MB limit." }),
        { status: 400, headers: corsHeaders }
      );
    }

    const ext = originalName.includes(".") ? path.extname(originalName) : (mimeType.includes("png") ? ".png" : mimeType.includes("webp") ? ".webp" : ".jpg");
    const uniqueFilename = `img_${Date.now()}_${Math.random().toString(36).substring(2, 9)}${ext}`;
    const filePath = path.join(uploadsDir, uniqueFilename);

    fs.writeFileSync(filePath, fileBuffer);

    // Build public URL
    const baseUrl = process.env.SHOPIFY_APP_URL || `${url.protocol}//${url.host}`;
    const publicUrl = `${baseUrl}/api/uploads/${uniqueFilename}`;

    return new Response(
      JSON.stringify({
        success: true,
        filename: uniqueFilename,
        url: publicUrl,
        mimeType,
        size: fileBuffer.length,
      }),
      { status: 200, headers: corsHeaders }
    );
  } catch (err: any) {
    logger.error("Upload error in /api/upload:", err);
    return new Response(
      JSON.stringify({ success: false, error: err?.message || "Internal server error during upload" }),
      { status: 500, headers: corsHeaders }
    );
  }
};
