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

import type { Project } from "../../../../src/shared/api";

import { InboxPage } from "../../../../src/web/features/inbox";
import { ProjectContext } from "../../../../src/web/shared/hooks/use-current-project";
import { installFetchMock, jsonResponse, renderWithProviders } from "../../test-utils";

const MOCK_PROJECT: Project = {
  archivedAt: null,
  createdAt: "2026-01-01T00:00:00.000Z",
  description: "",
  id: "project-1",
  name: "测试项目",
  status: "active",
  updatedAt: "2026-01-01T00:00:00.000Z",
};

const EMPTY_LIST = { items: [], page: 1, pageSize: 20, total: 0 };

function makeMaterial(overrides: Partial<{ description: string; id: string }> = {}) {
  return {
    associatedDate: "2026-06-03",
    createdAt: "2026-06-03T00:00:00.000Z",
    description: overrides.description ?? "测试素材",
    id: overrides.id ?? "mat-1",
    projectId: "project-1",
    status: "pending",
    updatedAt: "2026-06-03T00:00:00.000Z",
  };
}

function renderInboxPage() {
  return renderWithProviders(
    createElement(ProjectContext.Provider, {
      children: createElement(InboxPage),
      value: MOCK_PROJECT,
    }),
  );
}

describe("InboxPage", () => {
  test("初始状态显示空列表和空详情", async () => {
    const calls = installFetchMock((call) => {
      if (call.url.includes("/materials")) return jsonResponse(EMPTY_LIST);
      return jsonResponse({});
    });

    renderInboxPage();

    await waitFor(() => {
      expect(screen.getByText("暂无素材")).not.toBeNull();
    });
    expect(screen.getByText("请在左侧选择素材")).not.toBeNull();

    const listCall = calls.find((c) => c.url.includes("/materials") && c.method === "GET");
    expect(listCall).toBeDefined();
  });

  test("新增素材后列表追加且自动选中", async () => {
    const createdId = "mat-new";
    const created = makeMaterial({ description: "新增的素材", id: createdId });

    installFetchMock((call) => {
      if (call.method === "POST" && call.url.includes("/materials")) {
        return jsonResponse({ material: created }, { status: 201 });
      }
      if (call.method === "GET" && call.url.includes("/materials/" + createdId)) {
        return jsonResponse({ material: created });
      }
      if (call.method === "GET" && call.url.includes("/materials")) {
        return jsonResponse({ ...EMPTY_LIST, items: [created], total: 1 });
      }
      return jsonResponse({});
    });

    renderInboxPage();

    await waitFor(() => {
      expect(screen.getByRole("button", { name: /新增素材/ })).not.toBeNull();
    });

    fireEvent.click(screen.getByRole("button", { name: /新增素材/ }));

    await waitFor(() => {
      expect(screen.getByText("新增素材", { selector: ".ant-modal-title" })).not.toBeNull();
    });

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

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

    await waitFor(() => {
      const cards = screen.getAllByText("新增的素材");
      expect(cards.length).toBeGreaterThanOrEqual(1);
    });
  });

  test("删除素材后列表更新", async () => {
    let deleted = false;
    const material = makeMaterial({ description: "待删除的素材", id: "mat-del" });

    installFetchMock((call) => {
      if (call.method === "DELETE" && call.url.includes("/materials/" + material.id)) {
        deleted = true;
        return new Response(null, { status: 204 });
      }
      if (call.method === "GET" && call.url.includes("/materials")) {
        if (deleted) return jsonResponse(EMPTY_LIST);
        return jsonResponse({ ...EMPTY_LIST, items: [material], total: 1 });
      }
      return jsonResponse({});
    });

    renderInboxPage();

    await waitFor(() => {
      expect(screen.getByText("待删除的素材")).not.toBeNull();
    });

    fireEvent.click(screen.getByLabelText("删除"));

    await waitFor(() => {
      expect(screen.getByText("确认删除该素材？")).not.toBeNull();
    });

    fireEvent.click(screen.getByText("删 除"));

    await waitFor(() => {
      expect(screen.getByText("暂无素材")).not.toBeNull();
    });
  });
});
