import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createI18nMock } from "../../test/i18nMock";
import UserDetailPage from "./UserDetailPage";

const updateUserMock = vi.hoisted(() => vi.fn());
const profileRoleMock = vi.hoisted(() => ({ role: "super_admin" }));

vi.mock("../../lib/i18n", () => createI18nMock());

vi.mock("../../lib/adminApi", () => ({
  deleteUser: vi.fn(),
  fetchAllTenants: vi.fn(async () => ({
    items: [
      {
        id: "tenant-hanmac",
        type: "COMPANY",
        name: "한맥기술",
        slug: "hanmac",
        description: "",
        status: "active",
        memberCount: 1,
        createdAt: "2026-06-01T00:00:00Z",
        updatedAt: "2026-06-01T00:00:00Z",
      },
    ],
    total: 1,
  })),
  fetchMe: vi.fn(async () => ({
    id: "admin-user",
    role: profileRoleMock.role,
    name: "Admin",
    email: "admin@example.com",
  })),
  fetchGlobalCustomClaimDefinitions: vi.fn(async () => ({
    items: [
      {
        key: "contract_date",
        label: "계약일",
        valueType: "date",
        readPermission: "admin_only",
        writePermission: "admin_only",
        description: "",
      },
    ],
  })),
  fetchPasswordPolicy: vi.fn(async () => ({ minLength: 12 })),
  fetchTenant: vi.fn(),
  fetchUser: vi.fn(async () => ({
    id: "user-1",
    email: "user@example.com",
    name: "사용자",
    phone: "01012345678",
    role: "user",
    status: "active",
    tenantSlug: "hanmac",
    tenant: {
      id: "tenant-hanmac",
      type: "COMPANY",
      name: "한맥기술",
      slug: "hanmac",
      description: "",
      status: "active",
      memberCount: 1,
      createdAt: "2026-06-01T00:00:00Z",
      updatedAt: "2026-06-01T00:00:00Z",
    },
    joinedTenants: [],
    metadata: {
      employee_id: {
        "0": "h",
        "1": "j",
        "2": "k",
        "3": "w",
        "4": "o",
        "5": "n",
      },
      global_custom_claims: {
        contract_date: "2026-06-09",
      },
    },
    createdAt: "2026-06-01T00:00:00Z",
    updatedAt: "2026-06-01T00:00:00Z",
  })),
  fetchUserRpHistory: vi.fn(async () => []),
  updateUser: updateUserMock,
}));

function renderUserDetailPage() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  return render(
    <QueryClientProvider client={queryClient}>
      <MemoryRouter initialEntries={["/users/user-1"]}>
        <Routes>
          <Route path="/users/:id" element={<UserDetailPage />} />
        </Routes>
      </MemoryRouter>
    </QueryClientProvider>,
  );
}

describe("UserDetailPage Worksmobile employee number", () => {
  beforeEach(() => {
    updateUserMock.mockReset();
    updateUserMock.mockResolvedValue({});
    profileRoleMock.role = "super_admin";
  });

  it("shows and saves metadata employee_id from the user edit form", async () => {
    renderUserDetailPage();

    const employeeInput = await screen.findByLabelText("사번");

    expect(employeeInput).toHaveValue("hjkwon");

    fireEvent.change(employeeInput, { target: { value: "EMP001" } });
    fireEvent.click(screen.getByRole("button", { name: /저장하기/ }));

    await waitFor(() => expect(updateUserMock).toHaveBeenCalled());
    expect(updateUserMock).toHaveBeenCalledWith(
      "user-1",
      expect.objectContaining({
        metadata: expect.objectContaining({ employee_id: "EMP001" }),
      }),
    );
  });

  it("allows super admin to save a changed email", async () => {
    renderUserDetailPage();

    const emailInput = await screen.findByLabelText("이메일");
    fireEvent.change(emailInput, { target: { value: "changed@example.com" } });
    fireEvent.click(screen.getByRole("button", { name: /저장하기/ }));

    await waitFor(() => expect(updateUserMock).toHaveBeenCalled());
    expect(updateUserMock).toHaveBeenCalledWith(
      "user-1",
      expect.objectContaining({
        email: "changed@example.com",
      }),
    );
  });

  it("shows forbidden message for non-super admin", async () => {
    profileRoleMock.role = "tenant_admin";
    renderUserDetailPage();

    expect(
      await screen.findByText("이 작업을 수행할 권한이 없습니다."),
    ).toBeInTheDocument();
  });

  it("removes metadata employee_id when the field is cleared", async () => {
    renderUserDetailPage();

    const employeeInput = await screen.findByLabelText("사번");

    fireEvent.change(employeeInput, { target: { value: "" } });
    fireEvent.click(screen.getByRole("button", { name: /저장하기/ }));

    await waitFor(() => expect(updateUserMock).toHaveBeenCalled());
    const payload = updateUserMock.mock.calls[0][1];
    expect(payload.metadata).not.toHaveProperty("employee_id");
  });

  it("only allows editing per-user values for globally defined custom claims", async () => {
    renderUserDetailPage();

    const tab = await screen.findByTestId("global-custom-claim-tab");
    fireEvent.click(tab);

    expect(
      screen.queryByRole("button", { name: "추가" }),
    ).not.toBeInTheDocument();
    const valueInput = await screen.findByTestId(
      "global-custom-claim-value-contract_date",
    );

    expect(screen.getByText("contract_date")).toBeInTheDocument();
    expect(valueInput).toHaveValue("2026-06-09");
    expect(valueInput).toHaveAttribute("type", "date");

    fireEvent.change(valueInput, { target: { value: "2026-07-01" } });
    fireEvent.click(
      screen.getByRole("button", { name: /사용자 Claim 값 저장/ }),
    );

    await waitFor(() => expect(updateUserMock).toHaveBeenCalled());
    expect(updateUserMock).toHaveBeenCalledWith(
      "user-1",
      expect.objectContaining({
        metadata: expect.objectContaining({
          global_custom_claims: expect.objectContaining({
            contract_date: "2026-07-01",
          }),
          global_custom_claim_permissions: expect.objectContaining({
            contract_date: {
              readPermission: "admin_only",
              writePermission: "admin_only",
            },
          }),
        }),
      }),
    );
  });
});
