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

// ─── Pipeline Chains ───────────────────────────────────────────────
// Multi-step pipeline chain tests: combining different tool categories
// in realistic workflows. Complements pipeline-tools.spec.ts with
// more complex chains and cross-category combinations.

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));
}

function formatFixture(name: string): Buffer {
  return readFileSync(join(FORMATS, name));
}

const PNG_200x150 = fixture("test-200x150.png");
const JPG_100x100 = fixture("test-100x100.jpg");
const HEIC_200x150 = fixture("test-200x150.heic");
const JPG_SAMPLE = formatFixture("sample.jpg");
const JPG_WITH_EXIF = fixture("test-with-exif.jpg");

// ─── Resize + Watermark + Optimize Chain ───────────────────────────

test.describe("Resize + Watermark + Optimize chain", () => {
  test("resize then text watermark then optimize for web", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 800, fit: "contain" } },
            {
              toolId: "watermark-text",
              settings: {
                text: "PREVIEW",
                fontSize: 32,
                color: "#ffffff",
                opacity: 35,
                position: "center",
              },
            },
            { toolId: "optimize-for-web", settings: { maxWidth: 800, quality: 75 } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
    expect(body.processedSize).toBeLessThan(body.originalSize);
  });
});

// ─── Crop + Enhance + Convert Chain ────────────────────────────────

test.describe("Crop + Enhance + Convert chain", () => {
  test("crop then enhance then convert to WebP", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "crop", settings: { left: 10, top: 10, width: 200, height: 200 } },
            { toolId: "image-enhancement", settings: { preset: "auto" } },
            { toolId: "convert", settings: { format: "webp" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.downloadUrl).toContain(".webp");
  });
});

// ─── Strip Metadata + Resize + Compress Chain ──────────────────────

test.describe("Strip Metadata + Resize + Compress chain", () => {
  test("strip metadata then resize then compress", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "photo.jpg", mimeType: "image/jpeg", buffer: JPG_WITH_EXIF },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "strip-metadata", settings: {} },
            { toolId: "resize", settings: { width: 400, fit: "contain" } },
            { toolId: "compress", settings: { quality: 60 } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });
});

// ─── Color Adjust + Sharpen + Border Chain ─────────────────────────

test.describe("Color Adjust + Sharpen + Border chain", () => {
  test("adjust colors then sharpen then add border", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "adjust-colors", settings: { brightness: 10, contrast: 20 } },
            { toolId: "sharpening", settings: { sigma: 1.0 } },
            { toolId: "border", settings: { size: 10, color: "#333333" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Rotate + Crop + Watermark Chain ───────────────────────────────

test.describe("Rotate + Crop + Watermark chain", () => {
  test("rotate then crop then watermark text", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "rotate", settings: { angle: 90 } },
            { toolId: "crop", settings: { left: 0, top: 0, width: 300, height: 300 } },
            {
              toolId: "watermark-text",
              settings: {
                text: "ROTATED",
                fontSize: 24,
                color: "#ff0000",
                opacity: 50,
                position: "bottom-right",
              },
            },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Enhancement + Replace Color + Convert Chain ───────────────────

test.describe("Enhancement + Replace Color + Convert chain", () => {
  test("enhance then replace color then convert to AVIF", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "image-enhancement", settings: { preset: "vivid" } },
            {
              toolId: "replace-color",
              settings: {
                targetColor: "#ffffff",
                replacementColor: "#f0f0f0",
                tolerance: 20,
              },
            },
            { toolId: "convert", settings: { format: "avif" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.downloadUrl).toContain(".avif");
  });
});

// ─── HEIC Pipeline Chains ──────────────────────────────────────────

test.describe("HEIC pipeline chains", () => {
  test("HEIC: resize then convert to PNG", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.heic", mimeType: "image/heic", buffer: HEIC_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 100, fit: "contain" } },
            { toolId: "convert", settings: { format: "png" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.downloadUrl).toContain(".png");
  });

  test("HEIC: enhance then watermark then compress", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.heic", mimeType: "image/heic", buffer: HEIC_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "image-enhancement", settings: { preset: "auto" } },
            {
              toolId: "watermark-text",
              settings: {
                text: "HEIC PIPELINE",
                fontSize: 16,
                color: "#808080",
                opacity: 30,
                position: "bottom-right",
              },
            },
            { toolId: "compress", settings: { quality: 70 } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Grayscale + Sharpen + Text Overlay Chain ──────────────────────

test.describe("Grayscale + Sharpen + Text Overlay chain", () => {
  test("grayscale then sharpen then text overlay", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "adjust-colors", settings: { grayscale: true } },
            { toolId: "sharpening", settings: { sigma: 2.0 } },
            {
              toolId: "text-overlay",
              settings: {
                text: "B&W",
                fontSize: 48,
                color: "#FFFFFF",
                position: "bottom",
                backgroundBox: true,
                backgroundColor: "#000000",
              },
            },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Social Media Optimization Chain ───────────────────────────────

test.describe("Social media optimization chain", () => {
  test("resize for Instagram then enhance then watermark", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 1080, height: 1080, fit: "cover" } },
            { toolId: "image-enhancement", settings: { preset: "vivid" } },
            {
              toolId: "watermark-text",
              settings: {
                text: "@snapotter",
                fontSize: 16,
                color: "#ffffff",
                opacity: 30,
                position: "bottom-right",
              },
            },
            { toolId: "compress", settings: { quality: 85 } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
  });
});

// ─── Print Preparation Chain ───────────────────────────────────────

test.describe("Print preparation chain", () => {
  test("strip metadata then resize for A4 then sharpen then border", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "strip-metadata", settings: {} },
            { toolId: "resize", settings: { width: 2480, fit: "contain" } },
            { toolId: "sharpening", settings: { sigma: 1.2 } },
            { toolId: "border", settings: { size: 40, color: "#ffffff" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });
});

// ─── Thumbnail Generation Chain ────────────────────────────────────

test.describe("Thumbnail generation chain", () => {
  test("resize small then enhance then convert to WebP", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 150, height: 150, fit: "cover" } },
            { toolId: "sharpening", settings: { sigma: 0.5 } },
            { toolId: "convert", settings: { format: "webp" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.downloadUrl).toContain(".webp");
    expect(body.processedSize).toBeGreaterThan(0);
    // Thumbnail should be much smaller than original
    expect(body.processedSize).toBeLessThan(body.originalSize);
  });
});

// ─── Edit Metadata + Convert Chain ─────────────────────────────────

test.describe("Edit Metadata + Convert chain", () => {
  test("edit metadata then convert to PNG", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
        pipeline: JSON.stringify({
          steps: [
            {
              toolId: "edit-metadata",
              settings: { artist: "Pipeline Test", copyright: "CC0" },
            },
            { toolId: "convert", settings: { format: "png" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.downloadUrl).toContain(".png");
  });
});

// ─── Pipeline Chain Validation ─────────────────────────────────────

test.describe("Pipeline chain validation", () => {
  test("pipeline with duplicate steps succeeds", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 150, fit: "contain" } },
            { toolId: "resize", settings: { width: 100, fit: "contain" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
  });

  test("pipeline with 6 steps completes", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "sample.jpg", mimeType: "image/jpeg", buffer: JPG_SAMPLE },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "strip-metadata", settings: {} },
            { toolId: "resize", settings: { width: 600, fit: "contain" } },
            { toolId: "adjust-colors", settings: { brightness: 5, contrast: 10 } },
            { toolId: "sharpening", settings: { sigma: 0.8 } },
            {
              toolId: "watermark-text",
              settings: {
                text: "6-step",
                fontSize: 14,
                color: "#808080",
                opacity: 20,
                position: "bottom-right",
              },
            },
            { toolId: "compress", settings: { quality: 75 } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    expect(body.processedSize).toBeGreaterThan(0);
    expect(body.processedSize).toBeLessThan(body.originalSize);
  });

  test("pipeline step metadata is returned", async ({ request }) => {
    const res = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 100, fit: "contain" } },
            { toolId: "border", settings: { size: 5, color: "#000000" } },
          ],
        }),
      },
    });
    expect(res.ok()).toBe(true);
    const body = await res.json();
    expect(body.downloadUrl).toBeTruthy();
    // Pipeline should return step metadata
    if (body.steps) {
      expect(body.steps).toBeInstanceOf(Array);
      expect(body.steps.length).toBe(2);
    }
  });

  test("saved pipeline can be executed", async ({ request }) => {
    // Save a pipeline
    const saveRes = await request.post("/api/v1/pipeline/save", {
      headers: { Authorization: `Bearer ${token}` },
      data: {
        name: "Chain Test Pipeline",
        description: "Resize and convert for chain testing",
        steps: [
          { toolId: "resize", settings: { width: 200, fit: "contain" } },
          { toolId: "convert", settings: { format: "webp" } },
        ],
      },
    });
    expect(saveRes.ok()).toBe(true);
    const { id } = await saveRes.json();

    // Execute the saved pipeline
    const execRes = await request.post("/api/v1/pipeline/execute", {
      headers: { Authorization: `Bearer ${token}` },
      multipart: {
        file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
        pipeline: JSON.stringify({
          steps: [
            { toolId: "resize", settings: { width: 200, fit: "contain" } },
            { toolId: "convert", settings: { format: "webp" } },
          ],
        }),
      },
    });
    expect(execRes.ok()).toBe(true);
    const execBody = await execRes.json();
    expect(execBody.downloadUrl).toBeTruthy();
    expect(execBody.downloadUrl).toContain(".webp");

    // Clean up
    await request.delete(`/api/v1/pipeline/${id}`, {
      headers: { Authorization: `Bearer ${token}` },
    });
  });
});
