import { describe, expect, test, vi } from "bun:test";
import { fireEvent, screen, waitFor } from "@testing-library/react";
import { createElement } from "react";

import type { CreateMaterialRequest, Material } from "../../../../src/shared/api";

import { AddMaterialModal } from "../../../../src/web/features/inbox/components/AddMaterialModal";
import { renderWithProviders } from "../../test-utils";

const MOCK_CREATED: Material = {
  associatedDate: "2026-06-03",
  createdAt: "2026-06-03T00:00:00.000Z",
  description: "测试描述",
  id: "new-id",
  materialType: "general",
  processedContent: null,
  projectId: "project-1",
  status: "pending",
  updatedAt: "2026-06-03T00:00:00.000Z",
};

describe("AddMaterialModal", () => {
  test("打开时渲染表单字段", () => {
    renderWithProviders(
      createElement(AddMaterialModal, {
        onAdd: vi.fn(),
        onOpenChange: vi.fn(),
        open: true,
      }),
    );
    expect(screen.getByText("新增素材")).not.toBeNull();
    expect(screen.getByText("描述")).not.toBeNull();
    expect(screen.getByText("关联时间")).not.toBeNull();
  });

  test("关闭时不渲染", () => {
    renderWithProviders(
      createElement(AddMaterialModal, {
        onAdd: vi.fn(),
        onOpenChange: vi.fn(),
        open: false,
      }),
    );
    expect(screen.queryByText("新增素材")).toBeNull();
  });

  test("提交空表单显示必填校验", async () => {
    renderWithProviders(
      createElement(AddMaterialModal, {
        onAdd: vi.fn(),
        onOpenChange: vi.fn(),
        open: true,
      }),
    );

    fireEvent.click(screen.getByText("确 定"));

    await waitFor(() => {
      expect(screen.getByText("请输入描述")).not.toBeNull();
    });
  });

  test("点击确定触发表单提交", async () => {
    const onAdd = vi.fn<(body: CreateMaterialRequest) => Promise<Material>>();
    onAdd.mockResolvedValue(MOCK_CREATED);
    renderWithProviders(
      createElement(AddMaterialModal, {
        onAdd,
        onOpenChange: vi.fn(),
        open: true,
      }),
    );

    const textarea = screen.getByPlaceholderText("请输入素材描述");
    fireEvent.change(textarea, { target: { value: "测试描述" } });

    fireEvent.click(screen.getByText("确 定"));

    await waitFor(() => {
      expect(onAdd).toHaveBeenCalledTimes(1);
    });

    const callArgs = onAdd.mock.calls[0];
    expect(callArgs).toBeDefined();
    const calledBody = callArgs![0];
    expect(calledBody.description).toBe("测试描述");
    expect(calledBody.associatedDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
  });

  test("提交失败显示错误提示", async () => {
    const onAdd = vi.fn<(body: CreateMaterialRequest) => Promise<Material>>();
    onAdd.mockRejectedValue(new Error("网络错误"));
    renderWithProviders(
      createElement(AddMaterialModal, {
        onAdd,
        onOpenChange: vi.fn(),
        open: true,
      }),
    );

    const textarea = screen.getByPlaceholderText("请输入素材描述");
    fireEvent.change(textarea, { target: { value: "测试描述" } });

    fireEvent.click(screen.getByText("确 定"));

    await waitFor(() => {
      expect(onAdd).toHaveBeenCalledTimes(1);
    });
  });
});
