import React from "react";
import { readFileSync } from "node:fs";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { act, create, type ReactTestRenderer } from "react-test-renderer";

import { I18nProvider } from "../i18n/provider";
import FindInDatabaseModal from "./FindInDatabaseModal";

const mocks = vi.hoisted(() => ({
  dbQuery: vi.fn(),
  dbGetTables: vi.fn(),
  dbGetAllColumns: vi.fn(),
  message: {
    warning: vi.fn(),
    error: vi.fn(),
    info: vi.fn(),
  },
  storeState: {
    connections: [
      {
        id: "conn-1",
        config: {
          type: "mysql",
          host: "localhost",
          port: 3306,
          user: "root",
          password: "",
          database: "app",
        },
      },
    ],
    theme: "light",
  },
}));

vi.mock("../store", () => ({
  useStore: (selector: (state: typeof mocks.storeState) => unknown) => selector(mocks.storeState),
}));

vi.mock("../i18n/runtime", () => ({
  applyDayjsLocale: vi.fn(),
  syncLanguageRuntime: vi.fn(),
}));

vi.mock("../../wailsjs/go/app/App", () => ({
  DBQuery: mocks.dbQuery,
  DBGetTables: mocks.dbGetTables,
  DBGetAllColumns: mocks.dbGetAllColumns,
}));

vi.mock("antd", async () => {
  const React = await import("react");
  return {
    Modal: ({
      children,
      open,
      title,
    }: {
      children?: React.ReactNode;
      open?: boolean;
      title?: React.ReactNode;
    }) => (open ? React.createElement("section", null, title, children) : null),
    Input: ({
      placeholder,
      value,
      onChange,
    }: {
      placeholder?: string;
      value?: string;
      onChange?: (event: { target: { value: string } }) => void;
    }) =>
      React.createElement("input", {
        placeholder,
        value,
        onChange: (event: any) => onChange?.({ target: { value: event.target.value } }),
      }),
    Button: ({
      children,
      disabled,
      icon,
      onClick,
    }: {
      children?: React.ReactNode;
      disabled?: boolean;
      icon?: React.ReactNode;
      onClick?: () => void;
    }) => React.createElement("button", { disabled, onClick }, icon, children),
    Select: ({ options }: { options?: Array<{ label: React.ReactNode; value: string }> }) =>
      React.createElement(
        "div",
        null,
        options?.map((option) => React.createElement("span", { key: option.value }, option.label)),
      ),
    Table: ({ columns, dataSource }: { columns?: any[]; dataSource?: any[] }) =>
      React.createElement(
        "div",
        null,
        columns?.map((column) => React.createElement("span", { key: column.key || column.dataIndex }, column.title)),
        dataSource?.map((row, index) =>
          React.createElement(
            "div",
            { key: index },
            Object.values(row).map((value, valueIndex) =>
              React.createElement("span", { key: valueIndex }, String(value)),
            ),
          ),
        ),
      ),
    Progress: ({ percent }: { percent: number }) => React.createElement("div", null, `${percent}%`),
    Space: ({ children }: { children?: React.ReactNode }) => React.createElement("div", null, children),
    Tag: ({ children }: { children?: React.ReactNode }) => React.createElement("span", null, children),
    Tooltip: ({ children, title }: { children?: React.ReactNode; title?: React.ReactNode }) =>
      React.createElement("span", { title }, children),
    Empty: ({ description }: { description?: React.ReactNode }) => React.createElement("div", null, description),
    message: mocks.message,
  };
});

vi.mock("@ant-design/icons", async () => {
  const React = await import("react");
  const Icon = () => React.createElement("span", null);
  return {
    SearchOutlined: Icon,
    StopOutlined: Icon,
    EyeOutlined: Icon,
    DatabaseOutlined: Icon,
  };
});

const textContent = (node: any): string => {
  if (node === null || node === undefined) return "";
  if (typeof node === "string" || typeof node === "number") return String(node);
  if (Array.isArray(node)) return node.map((item) => textContent(item)).join("");
  return textContent(node.children || []);
};

const renderFindModal = () => {
  let renderer!: ReactTestRenderer;
  act(() => {
    renderer = create(
      <I18nProvider preference="en-US" onPreferenceChange={() => undefined}>
        <FindInDatabaseModal open connectionId="conn-1" dbName="app_db" onClose={vi.fn()} />
      </I18nProvider>,
    );
  });
  return renderer;
};

describe("FindInDatabaseModal i18n", () => {
  beforeEach(() => {
    mocks.dbQuery.mockReset();
    mocks.dbGetTables.mockReset();
    mocks.dbGetAllColumns.mockReset();
    mocks.message.warning.mockClear();
    mocks.message.error.mockClear();
    mocks.message.info.mockClear();
  });

  it("renders search chrome in the active language while preserving raw database name", () => {
    const renderer = renderFindModal();
    const renderedText = textContent(renderer.toJSON());
    const input = renderer.root.findByType("input");

    expect(renderedText).toContain("Search in database - app_db");
    expect(input.props.placeholder).toBe("Enter the string to search for...");
    expect(renderedText).toContain("Contains");
    expect(renderedText).toContain("Exact match");
    expect(renderedText).toContain("Search");
  });

  it("localizes controlled error wrappers while preserving backend detail", async () => {
    mocks.dbGetTables.mockResolvedValue({ success: false, message: "driver raw detail" });
    const renderer = renderFindModal();

    const input = renderer.root.findByType("input");
    await act(async () => {
      input.props.onChange({ target: { value: "alice" } });
    });

    const searchButton = renderer.root.findAllByType("button").find((button) => textContent(button).includes("Search"));
    expect(searchButton).toBeTruthy();

    await act(async () => {
      searchButton?.props.onClick();
      await Promise.resolve();
    });

    expect(mocks.message.error).toHaveBeenCalledWith("Failed to get table list: driver raw detail");
  });

  it("does not keep migrated Chinese UI literals in FindInDatabaseModal source", () => {
    const source = readFileSync(new URL("./FindInDatabaseModal.tsx", import.meta.url), "utf8");

    expect(source).not.toContain("请输入搜索关键字");
    expect(source).not.toContain("未找到连接配置");
    expect(source).not.toContain("获取表列表失败");
    expect(source).not.toContain("当前数据库没有表");
    expect(source).not.toContain("未找到匹配的数据");
    expect(source).not.toContain("搜索出错");
    expect(source).not.toContain("在数据库中搜索");
    expect(source).not.toContain("输入要搜索的字符串");
    expect(source).not.toContain("精确匹配");
    expect(source).not.toContain("匹配行详情");
  });
});
