// @vitest-environment jsdom

import { renderHook } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import type { PRMeta } from "./pr-meta";
import { useBumpExecute } from "./use-bump-execute";

function makePRMeta(): PRMeta {
  return {
    branchName: "branch",
    commitMessage: "commit",
    prTitle: "title",
    prBody: "body",
    scope: "scope",
    shortTag: "short",
  };
}

describe("useBumpExecute", () => {
  it("blocks file-sync execute when preview token is missing", async () => {
    const setError = vi.fn();
    const fetchMock = vi.fn();
    vi.stubGlobal("fetch", fetchMock);

    const { result } = renderHook(() =>
      useBumpExecute({
        mode: "file-sync",
        previewTokenId: "",
        prMeta: makePRMeta(),
        fileSyncSummary: null,
        fileSyncTargetIds: ["r1"],
        selectedIds: new Set(["r1"]),
        targetTag: "tag",
        component: "acs",
        selectedSections: new Set(),
        updateVariants: true,
        setBumping: vi.fn(),
        resetProgress: vi.fn(),
        setError,
        setFileSyncResult: vi.fn(),
        setStep: vi.fn(),
        enableImageTagCheck: true,
        appendProgress: vi.fn(),
      })
    );

    await result.current();

    expect(setError).toHaveBeenCalledWith("Missing preview token");
    expect(fetchMock).not.toHaveBeenCalled();
  });

  it("starts image execute and streams progress events", async () => {
    const setBumping = vi.fn();
    const resetProgress = vi.fn();
    const setError = vi.fn();
    const setStep = vi.fn();
    const appendProgress = vi.fn();

    const encoder = new TextEncoder();
    const stream = new ReadableStream<Uint8Array>({
      start(controller) {
        controller.enqueue(
          encoder.encode(
            `data: ${JSON.stringify({
              step: "precheck",
              status: "running",
              message: "Checking",
              at: "2026-05-27T00:00:00.000Z",
            })}\n\n`
          )
        );
        controller.close();
      },
    });

    vi.stubGlobal(
      "fetch",
      vi.fn(async () =>
        new Response(stream, {
          status: 200,
          headers: { "Content-Type": "text/event-stream" },
        })
      )
    );

    const { result } = renderHook(() =>
      useBumpExecute({
        mode: "image",
        previewTokenId: "",
        prMeta: makePRMeta(),
        fileSyncSummary: null,
        fileSyncTargetIds: [],
        selectedIds: new Set(["r1"]),
        targetTag: "tag",
        component: "acs",
        selectedSections: new Set(),
        updateVariants: true,
        enableImageTagCheck: true,
        setBumping,
        resetProgress,
        setError,
        setFileSyncResult: vi.fn(),
        setStep,
        appendProgress,
      })
    );

    await result.current();

    expect(setBumping).toHaveBeenCalledWith(true);
    expect(resetProgress).toHaveBeenCalled();
    expect(setError).toHaveBeenCalledWith("");
    expect(setStep).toHaveBeenCalledWith("execute");
    expect(appendProgress).toHaveBeenCalled();
    expect(setBumping).toHaveBeenLastCalledWith(false);
  });

  it("passes enableImageTagCheck in image bump request body", async () => {
    const fetchCalls: RequestInit[] = [];

    vi.stubGlobal(
      "fetch",
      vi.fn(async (_url: string, init: RequestInit) => {
        fetchCalls.push(init);
        const encoder = new TextEncoder();
        const stream = new ReadableStream<Uint8Array>({
          start(controller) {
            controller.enqueue(
              encoder.encode(
                `data: ${JSON.stringify({
                  step: "precheck",
                  status: "success",
                  message: "Done",
                  at: "2026-05-27T00:00:00.000Z",
                })}\n\n`
              )
            );
            controller.close();
          },
        });
        return new Response(stream, {
          status: 200,
          headers: { "Content-Type": "text/event-stream" },
        });
      })
    );

    const { result } = renderHook(() =>
      useBumpExecute({
        mode: "image",
        previewTokenId: "",
        prMeta: makePRMeta(),
        fileSyncSummary: null,
        fileSyncTargetIds: [],
        selectedIds: new Set(["r1"]),
        targetTag: "tag",
        component: "acs",
        selectedSections: new Set(),
        updateVariants: true,
        enableImageTagCheck: false,
        setBumping: vi.fn(),
        resetProgress: vi.fn(),
        setError: vi.fn(),
        setFileSyncResult: vi.fn(),
        setStep: vi.fn(),
        appendProgress: vi.fn(),
      })
    );

    await result.current();

    expect(fetchCalls).toHaveLength(1);
    const body = JSON.parse(fetchCalls[0].body as string);
    expect(body.enableImageTagCheck).toBe(false);
  });
});
