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

import type { Model, Provider, ProviderOption } from "../../../src/shared/api";

import { ModelTable } from "../../../src/web/features/models/components/ModelTable";
import { ProviderTable } from "../../../src/web/features/models/components/ProviderTable";
import { renderWithProviders } from "../test-utils";

const OPENAI_PROVIDER_OPTION: ProviderOption = {
  id: "pv1",
  name: "OpenAI",
  type: "openai",
};

const DEEPSEEK_PROVIDER_OPTION: ProviderOption = {
  id: "pv2",
  name: "DeepSeek",
  type: "openai-compatible",
};

const ENABLED_MODEL: Model = {
  capabilities: ["text", "reasoning"],
  contextLength: 128000,
  createdAt: "2024-01-01T00:00:00.000Z",
  externalId: "gpt-4o",
  id: "m1",
  maxOutputTokens: 4096,
  name: "GPT-4o",
  providerId: "pv1",
  updatedAt: "2024-01-01T00:00:00.000Z",
};

const DISABLED_MODEL: Model = {
  capabilities: ["text"],
  contextLength: null,
  createdAt: "2024-01-01T00:00:00.000Z",
  externalId: "deepseek-chat",
  id: "m2",
  maxOutputTokens: null,
  name: "DeepSeek Chat",
  providerId: "pv2",
  updatedAt: "2024-01-01T00:00:00.000Z",
};

const OPENAI_PROVIDER: Provider = {
  apiKey: "sk-test",
  baseUrl: "https://api.openai.com/v1",
  createdAt: "2024-01-01T00:00:00.000Z",
  id: "pv1",
  name: "OpenAI",
  type: "openai",
  updatedAt: "2024-01-01T00:00:00.000Z",
};

const DEEPSEEK_PROVIDER: Provider = {
  apiKey: "sk-off",
  baseUrl: "https://api.deepseek.com/v1",
  createdAt: "2024-01-01T00:00:00.000Z",
  id: "pv2",
  name: "DeepSeek",
  type: "openai-compatible",
  updatedAt: "2024-01-01T00:00:00.000Z",
};

function clickLatestConfirmButton() {
  const buttons = screen.getAllByRole("button", { name: /OK|确定/ });
  fireEvent.click(buttons[buttons.length - 1]!);
}

function renderModelTable(overrides?: Record<string, unknown>) {
  renderWithProviders(
    createElement(ModelTable, {
      data: { items: [ENABLED_MODEL, DISABLED_MODEL], page: 1, pageSize: 20, total: 2 },
      loading: false,
      onChange: () => undefined,
      onDelete: () => Promise.resolve(),
      onEdit: () => undefined,
      page: 1,
      pageSize: 20,
      providers: [OPENAI_PROVIDER_OPTION, DEEPSEEK_PROVIDER_OPTION],
      ...overrides,
    }),
  );
}

function renderProviderTable(overrides?: Record<string, unknown>) {
  renderWithProviders(
    createElement(ProviderTable, {
      data: { items: [OPENAI_PROVIDER, DEEPSEEK_PROVIDER], page: 1, pageSize: 20, total: 2 },
      loading: false,
      onChange: () => undefined,
      onDelete: () => Promise.resolve(),
      onEdit: () => undefined,
      page: 1,
      pageSize: 20,
      ...overrides,
    }),
  );
}

const TABLE_TEST_CASES = [
  {
    assertData: () => {
      expect(screen.getByText("GPT-4o")).not.toBeNull();
      expect(screen.getByText("DeepSeek Chat")).not.toBeNull();
      expect(screen.getByText("OpenAI")).not.toBeNull();
      expect(screen.getByText("DeepSeek")).not.toBeNull();
    },
    assertNoExtra: () => {
      expect(screen.queryByText("状态")).toBeNull();
      expect(screen.queryByRole("button", { name: /启用|禁用/ })).toBeNull();
    },
    componentName: "ModelTable",
    render: () => renderModelTable(),
  },
  {
    assertData: () => {
      expect(screen.getAllByText("OpenAI").length).toBeGreaterThan(0);
      expect(screen.getByText("DeepSeek")).not.toBeNull();
      expect(screen.getByText("https://api.openai.com/v1")).not.toBeNull();
    },
    assertNoExtra: () => {
      expect(screen.queryByText("状态")).toBeNull();
      expect(screen.queryByRole("button", { name: "测试连接" })).toBeNull();
      expect(screen.queryByRole("button", { name: /启用|禁用/ })).toBeNull();
    },
    componentName: "ProviderTable",
    render: () => renderProviderTable(),
  },
];

const TABLE_ACTION_TEST_CASES = [
  {
    componentName: "ModelTable",
    deleteConfirmText: "确认删除此模型？",
    deleteId: "m1",
    editArg: ENABLED_MODEL,
    render: (overrides?: Record<string, unknown>) => renderModelTable(overrides),
  },
  {
    componentName: "ProviderTable",
    deleteConfirmText: "确认删除此供应商？",
    deleteId: "pv1",
    editArg: OPENAI_PROVIDER,
    render: (overrides?: Record<string, unknown>) => renderProviderTable(overrides),
  },
];

describe("ResourceTable", () => {
  for (const tc of TABLE_TEST_CASES) {
    test(`${tc.componentName} 渲染表格数据`, () => {
      tc.render();
      tc.assertData();
      tc.assertNoExtra();
    });
  }

  for (const tc of TABLE_ACTION_TEST_CASES) {
    test(`${tc.componentName} 表格操作触发 edit/delete`, async () => {
      const onDelete = mock(() => Promise.resolve());
      const onEdit = mock(() => undefined);

      tc.render({ onDelete, onEdit });

      fireEvent.click(screen.getAllByRole("button", { name: /编辑/ })[0]!);
      expect(onEdit).toHaveBeenCalledWith(tc.editArg);

      fireEvent.click(screen.getAllByRole("button", { name: /删除/ })[0]!);
      await waitFor(() => expect(screen.getByText(tc.deleteConfirmText)).not.toBeNull());
      clickLatestConfirmButton();
      await waitFor(() => expect(onDelete).toHaveBeenCalledWith(tc.deleteId));
    });
  }
});
