import { ToolcraftSceneExportError } from "../../../export/export-frame";
import { defaultToolcraftRuntimeSceneVisibility } from "../../../scene";
import type { ToolcraftActionSchema } from "../../../schema/types";
import {
  act,
  defineToolcraft,
  fireEvent,
  renderControlsPanelWithSchema,
  screen,
  vi,
} from "../testing/controls-panel-test-utils";
import { describe, expect, it } from "vitest";

function createExportSchema(
  actions: readonly ToolcraftActionSchema[] = [
    { label: "Export PNG", value: "export", variant: "default" },
  ],
) {
  return defineToolcraft({
    canvas: { enabled: true, size: { height: 180, unit: "px", width: 320 } },
    panels: {
      controls: {
        sections: [
          {
            actionGroup: "secondary",
            controls: {
              footer: {
                actions,
                target: "panel.actions",
                type: "panelActions",
              },
            },
          },
        ],
        title: "Controls",
      },
    },
  });
}

describe("ControlsPanel scene export actions", () => {
  it("shows only feedback reported by the latest panel action", async () => {
    const schema = createExportSchema([
      { label: "First export", value: "first", variant: "secondary" },
      { label: "Second export", value: "second", variant: "default" },
    ]);
    const reporters: Array<(feedback: { code: string; message: string }) => void> = [];

    renderControlsPanelWithSchema(schema, {
      onPanelAction: ({ reportFeedback }) => {
        reporters.push(reportFeedback);
      },
    });
    fireEvent.click(screen.getByRole("button", { name: "First export" }));
    fireEvent.click(screen.getByRole("button", { name: "Second export" }));

    act(() => reporters[0]?.({ code: "stale", message: "Stale failure" }));
    expect(screen.queryByRole("alert")).toBeNull();

    act(() => {
      reporters[1]?.({ code: "empty-scene", message: "Nothing to export" });
    });
    const alert = await screen.findByRole("alert");
    expect(alert.textContent).toBe("Nothing to export");
    expect(alert.getAttribute("data-panel-action-feedback-code")).toBe("empty-scene");
  });

  it("presents a missing required bounds provider as typed visible feedback", async () => {
    const onPanelAction = vi.fn();
    renderControlsPanelWithSchema(
      createExportSchema([
        {
          command: "controls.apply",
          label: "Export PNG",
          role: "export-image",
          value: "export",
          variant: "default",
        },
      ]),
      {
        sceneExport: {
          exportRenderer: {
            baseFileName: "scene",
            renderFrame: vi.fn(),
          },
          productSceneRequired: true,
          visibility: defaultToolcraftRuntimeSceneVisibility,
        },
        onPanelAction,
      },
      { canvas: { mode: "infinite" } },
    );
    fireEvent.click(screen.getByRole("button", { name: "Export PNG" }));

    const alert = await screen.findByRole("alert");
    expect(alert.getAttribute("data-panel-action-feedback-code")).toBe(
      "scene-bounds-unavailable",
    );
    expect(alert.textContent).toContain("does not provide export bounds");
    expect(onPanelAction).not.toHaveBeenCalled();
  });

  it("presents rejected typed export failures as visible feedback", async () => {
    renderControlsPanelWithSchema(createExportSchema(), {
      onPanelAction: async () => {
        throw new ToolcraftSceneExportError({
          code: "scene-export-too-large",
          message: "The cropped scene is too large to export.",
          ok: false,
        });
      },
    });
    fireEvent.click(screen.getByRole("button", { name: "Export PNG" }));

    const alert = await screen.findByRole("alert");
    expect(alert.getAttribute("data-panel-action-feedback-code")).toBe(
      "scene-export-too-large",
    );
    expect(alert.textContent).toBe("The cropped scene is too large to export.");
  });

  it("routes typed SVG export through runtime and never through onPanelAction", async () => {
    const onPanelAction = vi.fn();
    const renderFrame = vi.fn();
    renderControlsPanelWithSchema(
      createExportSchema([
        {
          label: "Export SVG",
          role: "export-svg",
          value: "export.svg",
          variant: "default",
        },
      ]),
      {
        onPanelAction,
        sceneExport: {
          productSceneRequired: false,
          svgExportRenderer: {
            baseFileName: "scene",
            renderFrame,
          },
          visibility: defaultToolcraftRuntimeSceneVisibility,
        },
      },
    );

    const exportButton = screen.getByRole("button", { name: "Export SVG" });
    expect(
      exportButton.querySelector('[data-icon-name="upload-simple"]'),
    ).toBeTruthy();
    fireEvent.click(exportButton);

    const alert = await screen.findByRole("alert");
    expect(renderFrame).toHaveBeenCalledOnce();
    expect(alert.getAttribute("data-panel-action-feedback-code")).toBe(
      "svg-content-empty",
    );
    expect(onPanelAction).not.toHaveBeenCalled();
  });
});
