import { readFileSync } from "node:fs";
import { join } from "node:path";
import { expect, test } from "@playwright/test";

// ─── Adjustment Tools ───────────────────────────────────────────────
// Tests for: color-adjustments, sharpening, replace-color, strip-metadata,
// edit-metadata, optimize-for-web, image-enhancement
// These tools modify image properties without changing dimensions.

const FIXTURES = join(process.cwd(), "tests", "fixtures");
const FORMATS = join(FIXTURES, "formats");

let token: string;

test.beforeAll(async ({ request }) => {
  const res = await request.post("/api/auth/login", {
    data: { username: "admin", password: "admin" },
  });
  const body = await res.json();
  token = body.token;
});

function fixture(name: string): Buffer {
  return readFileSync(join(FIXTURES, name));
}

const PNG_200x150 = fixture("test-200x150.png");
const JPG_100x100 = fixture("test-100x100.jpg");
const JPG_WITH_EXIF = fixture("test-with-exif.jpg");
const JPG_SAMPLE = readFileSync(join(FORMATS, "sample.jpg"));

// ─── Color Adjustments ──────────────────────────────────────────────

test.describe("Color Adjustments", () => {
  test("adjust brightness", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ brightness: 20 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("adjust contrast", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ contrast: 30 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("adjust saturation", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ saturation: -20 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("apply grayscale", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ grayscale: true }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("multiple adjustments at once", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({
          brightness: 10,
          contrast: 15,
          saturation: -10,
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Sharpening ─────────────────────────────────────────────────────

test.describe("Sharpening", () => {
  test("sharpen with default settings", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/sharpening", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({}),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("sharpen with explicit sigma and amount", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/sharpening", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ sigma: 1.5, amount: 1.0 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("heavy sharpening changes file size", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/sharpening", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        settings: JSON.stringify({ sigma: 3.0, amount: 2.0 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    // Sharpening adds high-frequency detail, so file may differ in size
    expect(body.processedSize).toBeGreaterThan(0);
  });
});

// ─── Replace Color ──────────────────────────────────────────────────

test.describe("Replace Color", () => {
  test("replace white with black", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/replace-color", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({
          targetColor: "#ffffff",
          replacementColor: "#000000",
          tolerance: 30,
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("replace with low tolerance", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/replace-color", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({
          targetColor: "#ff0000",
          replacementColor: "#00ff00",
          tolerance: 5,
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("replace with high tolerance", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/replace-color", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({
          targetColor: "#808080",
          replacementColor: "#0000ff",
          tolerance: 80,
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Strip Metadata ─────────────────────────────────────────────────

test.describe("Strip Metadata", () => {
  test("strip metadata from JPEG with EXIF", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/strip-metadata", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_WITH_EXIF },
        settings: JSON.stringify({}),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
    // Stripped image should be smaller or equal (no EXIF overhead)
    expect(body.processedSize).toBeLessThanOrEqual(body.originalSize);
  });

  test("strip metadata from PNG", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/strip-metadata", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({}),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("stripped image has no EXIF data", async ({ request }) => {
    // First strip metadata
    const stripRes = await request.post("/api/v1/tools/image/strip-metadata", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_WITH_EXIF },
        settings: JSON.stringify({}),
      },
    });
    expect(stripRes.ok()).toBe(true);
    const stripBody = await stripRes.json();

    // Download the stripped image
    const downloadRes = await request.get(stripBody.downloadUrl, {
      headers: { Authorization: `Bearer ${token}` },
    });
    expect(downloadRes.ok()).toBe(true);
    const strippedBuffer = Buffer.from(await downloadRes.body());

    // Verify stripped image via info tool
    const infoRes = await request.post("/api/v1/tools/image/info", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "stripped.jpg", mimeType: "image/jpeg", buffer: strippedBuffer },
      },
    });
    expect(infoRes.ok()).toBe(true);
    const infoBody = await infoRes.json();
    expect(infoBody.hasExif).toBe(false);
  });
});

// ─── Edit Metadata ──────────────────────────────────────────────────

test.describe("Edit Metadata", () => {
  test("set artist and copyright fields", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/edit-metadata", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({
          artist: "Test Artist",
          copyright: "CC-BY-4.0",
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("edit metadata on PNG", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/edit-metadata", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({
          title: "Test Image",
          description: "A test image for e2e testing",
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Optimize for Web ───────────────────────────────────────────────

test.describe("Optimize for Web", () => {
  test("optimize with default settings", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/optimize-for-web", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        settings: JSON.stringify({}),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("optimize with maxWidth constraint", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/optimize-for-web", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        settings: JSON.stringify({ maxWidth: 800, quality: 75 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    // Optimized should be smaller than the original large sample
    expect(body.processedSize).toBeLessThan(body.originalSize);
  });

  test("optimize PNG image", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/optimize-for-web", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ maxWidth: 1920, quality: 80 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Image Enhancement ──────────────────────────────────────────────

test.describe("Image Enhancement", () => {
  test("auto enhancement", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/image-enhancement", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ preset: "auto" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("vivid enhancement preset", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/image-enhancement", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ preset: "vivid" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("enhancement changes the image", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/image-enhancement", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        settings: JSON.stringify({ preset: "auto" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    // Enhanced image should differ from original
    expect(body.processedSize).toBeGreaterThan(0);
    expect(body.processedSize).not.toBe(body.originalSize);
  });
});

// ─── Color Blindness Simulation ────────────────────────────────────

test.describe("Color Blindness Simulation", () => {
  test("simulate deuteranomaly (default)", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({}),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });

  test("simulate protanopia on JPEG", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ simulationType: "protanopia" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("simulate tritanopia", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ simulationType: "tritanopia" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("simulate achromatopsia (total color blindness)", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ simulationType: "achromatopsia" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("simulate protanomaly", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ simulationType: "protanomaly" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("simulate tritanomaly", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        settings: JSON.stringify({ simulationType: "tritanomaly" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("simulate blueConeMonochromacy", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ simulationType: "blueConeMonochromacy" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("color-blindness on HEIC image", async ({ request }) => {
    const heic = readFileSync(join(FIXTURES, "test-200x150.heic"));
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.heic", mimeType: "image/heic", buffer: heic },
        settings: JSON.stringify({ simulationType: "deuteranopia" }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Color Adjustments — Additional ────────────────────────────────

test.describe("Color Adjustments — additional", () => {
  test("adjust hue rotation", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ hue: 90 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("extreme brightness and contrast", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ brightness: 100, contrast: 100 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("color adjustments on HEIC image", async ({ request }) => {
    const heic = readFileSync(join(FIXTURES, "test-200x150.heic"));
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.heic", mimeType: "image/heic", buffer: heic },
        settings: JSON.stringify({ brightness: 15, saturation: 10 }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Auth Failure ──────────────────────────────────────────────────

test.describe("Auth failure", () => {
  test("adjust-colors without token returns 401", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/adjust-colors", {
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({ brightness: 20 }),
      },
    });
    expect(res.status()).toBe(401);
  });

  test("strip-metadata without token returns 401", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/strip-metadata", {
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_WITH_EXIF },
        settings: JSON.stringify({}),
      },
    });
    expect(res.status()).toBe(401);
  });

  test("edit-metadata without token returns 401", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/edit-metadata", {
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        settings: JSON.stringify({ artist: "Test" }),
      },
    });
    expect(res.status()).toBe(401);
  });

  test("color-blindness without token returns 401", async ({ request }) => {
    const res = await request.post("/api/v1/tools/image/color-blindness", {
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        settings: JSON.stringify({}),
      },
    });
    expect(res.status()).toBe(401);
  });
});
