import { useApolloClient } from "@apollo/client/react";
import { Form } from "antd";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { useEffect } from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
  DELETE_VACATION,
  INSERT_EMPLOYEES,
  QUERY_EMPLOYEE_BY_ID,
  UPDATE_EMPLOYEE
} from "../../graphql/employees.queries";
import { ShopEmployeesFormComponent } from "./shop-employees-form.component.jsx";

const insertEmployeesMock = vi.fn();
const updateEmployeeMock = vi.fn();
const deleteVacationMock = vi.fn();
const useQueryMock = vi.fn();
const useMutationMock = vi.fn();
const navigateMock = vi.fn();
const notification = {
  error: vi.fn(),
  success: vi.fn()
};

vi.mock("@apollo/client/react", async () => {
  const actual = await vi.importActual("@apollo/client/react");

  return {
    ...actual,
    useApolloClient: vi.fn(),
    useQuery: (...args) => useQueryMock(...args),
    useMutation: (...args) => useMutationMock(...args)
  };
});

vi.mock("@splitsoftware/splitio-react", () => ({
  useTreatmentsWithConfig: () => ({
    treatments: {
      Enhanced_Payroll: {
        treatment: "off"
      }
    }
  })
}));

vi.mock("react-router-dom", () => ({
  useLocation: () => ({
    search: "?employeeId=new"
  }),
  useNavigate: () => navigateMock
}));

vi.mock("react-i18next", () => ({
  useTranslation: () => ({
    t: (key, values = {}) => {
      const translations = {
        "bodyshop.labels.employee_options": "Employee Options",
        "bodyshop.labels.employee_rates": "Employee Rates",
        "bodyshop.labels.employee_vacation": "Employee Vacation",
        "bodyshop.labels.employees": "Employees",
        "employees.actions.addrate": "Add Rate",
        "employees.actions.addvacation": "Add Vacation",
        "employees.actions.new": "New Employee",
        "employees.actions.save_employee": "Save Employee",
        "employees.fields.active": "Active",
        "employees.fields.employee_number": "Employee Number",
        "employees.fields.external_id": "External Id",
        "employees.fields.first_name": "First Name",
        "employees.fields.flat_rate": "Flat Rate",
        "employees.fields.hire_date": "Hire Date",
        "employees.fields.last_name": "Last Name",
        "employees.fields.pin": "PIN",
        "employees.fields.rate": "Rate",
        "employees.fields.termination_date": "Termination Date",
        "employees.fields.user_email": "User Email",
        "employees.labels.active": "Active",
        "employees.successes.save": "Saved",
        "general.actions.saveandnew": "Save and New",
        "general.labels.actions": "Actions"
      };

      if (key === "employees.errors.save") {
        return `Save failed: ${values.message ?? ""}`;
      }

      if (key === "employees.validation.unique_employee_number") {
        return "Employee number must be unique";
      }

      if (key === "bodyshop.validation.useremailmustexist") {
        return "User email must exist";
      }

      return translations[key] || key;
    }
  })
}));

vi.mock("../../contexts/Notifications/notificationContext.jsx", () => ({
  useNotification: () => notification
}));

vi.mock("../../firebase/firebase.utils", () => ({
  logImEXEvent: vi.fn()
}));

vi.mock("../alert/alert.component", () => ({
  default: ({ title }) => <div>{title}</div>
}));

vi.mock("../form-fields-changed-alert/form-fields-changed-alert.component.jsx", () => ({
  default: () => null
}));

vi.mock("../form-date-time-picker/form-date-time-picker.component.jsx", () => ({
  default: ({ id, value, onChange }) => (
    <input id={id} type="text" value={value ?? ""} onChange={(event) => onChange?.(event.target.value)} />
  )
}));

vi.mock("../form-items-formatted/email-form-item.component.jsx", () => ({
  default: ({ id, value, onChange }) => (
    <input id={id} type="email" value={value ?? ""} onChange={(event) => onChange?.(event.target.value)} />
  )
}));

vi.mock("../layout-form-row/layout-form-row.component", () => ({
  default: ({ title, extra, actions, children }) => (
    <div>
      {title}
      {extra}
      {children}
      {actions}
    </div>
  )
}));

vi.mock("../layout-form-row/inline-validated-form-row.component.jsx", () => ({
  default: ({ title, extra, children }) => (
    <div>
      {title}
      {extra}
      {children}
    </div>
  )
}));

vi.mock("../layout-form-row/config-list-empty-state.component.jsx", () => ({
  default: ({ actionLabel }) => <div>{actionLabel}</div>
}));

vi.mock("../form-list-move-arrows/form-list-move-arrows.component", () => ({
  default: () => null
}));

vi.mock("../responsive-table/responsive-table.component", () => ({
  default: () => null
}));

vi.mock("./shop-employees-add-vacation.component", () => ({
  default: () => null
}));

vi.mock("../../utils/Ciecaselect", () => ({
  default: () => []
}));

const bodyshop = {
  id: "shop-1",
  imexshopid: "split-shop-1",
  md_responsibility_centers: {
    costs: []
  }
};

describe("ShopEmployeesFormComponent", () => {
  let formInstance;

  beforeEach(() => {
    vi.clearAllMocks();

    useQueryMock.mockImplementation((query) => {
      if (query === QUERY_EMPLOYEE_BY_ID) {
        return {
          error: null,
          data: null,
          refetch: vi.fn(),
          loading: false
        };
      }

      return {
        error: null,
        data: null,
        loading: false
      };
    });

    useMutationMock.mockImplementation((mutation) => {
      if (mutation === INSERT_EMPLOYEES) return [insertEmployeesMock];
      if (mutation === UPDATE_EMPLOYEE) return [updateEmployeeMock];
      if (mutation === DELETE_VACATION) return [deleteVacationMock];
      return [vi.fn()];
    });

    useApolloClient.mockReturnValue({
      query: vi.fn().mockResolvedValue({
        data: {
          employees_aggregate: {
            aggregate: {
              count: 0
            },
            nodes: []
          },
          users: []
        }
      })
    });

    insertEmployeesMock.mockResolvedValue({
      data: {
        insert_employees: {
          returning: [
            {
              id: "employee-123",
              first_name: "Jamie",
              last_name: "Rivera",
              employee_number: "42",
              active: true,
              termination_date: null,
              hire_date: "2026-04-20",
              flat_rate: false,
              rates: [],
              pin: "1234",
              user_email: null
            }
          ]
        }
      }
    });

    function TestHarness({ onFormReady }) {
      const [form] = Form.useForm();

      useEffect(() => {
        onFormReady(form);
      }, [form, onFormReady]);

      return <ShopEmployeesFormComponent bodyshop={bodyshop} form={form} />;
    }

    render(
      <TestHarness
        onFormReady={(form) => {
          formInstance = form;
        }}
      />
    );
  });

  it("marks a new employee form clean after save", async () => {
    fireEvent.change(screen.getByRole("textbox", { name: "First Name" }), {
      target: { value: "Jamie" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Last Name" }), {
      target: { value: "Rivera" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Employee Number" }), {
      target: { value: "42" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "PIN" }), {
      target: { value: "1234" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Hire Date" }), {
      target: { value: "2026-04-20" }
    });

    const saveButton = screen.getByRole("button", { name: "Save Employee" });

    await waitFor(() => {
      expect(saveButton.disabled).toBe(false);
    });

    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(insertEmployeesMock).toHaveBeenCalledWith({
        variables: {
          employees: [
            expect.objectContaining({
              first_name: "Jamie",
              last_name: "Rivera",
              employee_number: "42",
              pin: "1234",
              hire_date: "2026-04-20",
              shopid: "shop-1"
            })
          ]
        },
        refetchQueries: ["QUERY_EMPLOYEES"]
      });
    });

    await waitFor(() => {
      expect(formInstance.isFieldsTouched()).toBe(false);
    });

    expect(notification.success).toHaveBeenCalledWith({
      title: "Saved"
    });
    expect(navigateMock).toHaveBeenCalledWith({
      search: "employeeId=employee-123"
    });
  });

  it("saves a new employee and opens a fresh employee form when save and new is clicked", async () => {
    fireEvent.change(screen.getByRole("textbox", { name: "First Name" }), {
      target: { value: "Jamie" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Last Name" }), {
      target: { value: "Rivera" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Employee Number" }), {
      target: { value: "42" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "PIN" }), {
      target: { value: "1234" }
    });
    fireEvent.change(screen.getByRole("textbox", { name: "Hire Date" }), {
      target: { value: "2026-04-20" }
    });

    fireEvent.click(screen.getByRole("button", { name: "Save and New" }));

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

    await waitFor(() => {
      expect(formInstance.isFieldsTouched()).toBe(false);
    });

    await waitFor(() => {
      expect(screen.getByRole("textbox", { name: "First Name" })).toHaveValue("");
      expect(screen.getByRole("textbox", { name: "Last Name" })).toHaveValue("");
      expect(screen.getByRole("textbox", { name: "Employee Number" })).toHaveValue("");
      expect(screen.getByRole("textbox", { name: "PIN" })).toHaveValue("");
      expect(screen.getByRole("textbox", { name: "Hire Date" })).toHaveValue("");
    });

    expect(screen.getByText("New Employee")).toBeInTheDocument();
    expect(navigateMock).toHaveBeenCalledWith({
      search: "employeeId=new"
    });
    expect(notification.success).toHaveBeenCalledWith({
      title: "Saved"
    });
  });
});
