import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import DynamicListTypeInput from "../pages/GlobalConfig/Inputs/DynamicListTypeInput.js";
import { jest } from "@jest/globals";
import "@testing-library/jest-dom";

// Mock the recheck module
jest.unstable_mockModule("recheck", () => ({
  check: jest.fn().mockResolvedValue(true),
}));

describe("DynamicListTypeInput", () => {
  const mockOnChange = jest.fn();
  const defaultField = {
    Label: "Test Label",
    Placeholder: "Enter value",
    ProValue: "",
    Pattern: "",
    ErrorText: "Invalid format",
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it("renders with label and placeholder", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    expect(screen.getByLabelText(/Test Label/i)).toBeInTheDocument();
    expect(screen.getByPlaceholderText("Enter value")).toBeInTheDocument();
  });

  it("renders with existing values as chips", () => {
    const fieldWithValues = {
      ...defaultField,
      ProValue: "value1,value2",
    };

    render(
      <DynamicListTypeInput
        field={fieldWithValues}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    expect(screen.getByText("value1")).toBeInTheDocument();
    expect(screen.getByText("value2")).toBeInTheDocument();
  });

  it("renders with array ProValue", () => {
    const fieldWithArrayValues = {
      ...defaultField,
      ProValue: ["item1", "item2"],
    };

    render(
      <DynamicListTypeInput
        field={fieldWithArrayValues}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    expect(screen.getByText("item1")).toBeInTheDocument();
    expect(screen.getByText("item2")).toBeInTheDocument();
  });

  it("adds value when Add button is clicked", async () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "newvalue" } });

    const addButton = screen.getByText("Add");
    fireEvent.click(addButton);

    await waitFor(() => {
      expect(mockOnChange).toHaveBeenCalledWith(["newvalue"]);
    });
  });

  it("adds value when Enter key is pressed", async () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "entervalue" } });
    fireEvent.keyDown(input, { key: "Enter", code: "Enter" });

    await waitFor(() => {
      expect(mockOnChange).toHaveBeenCalledWith(["entervalue"]);
    });
  });

  it("does not add duplicate values", async () => {
    const fieldWithValue = {
      ...defaultField,
      ProValue: "existing",
    };

    render(
      <DynamicListTypeInput
        field={fieldWithValue}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "existing" } });

    const addButton = screen.getByText("Add");
    fireEvent.click(addButton);

    // Should not call onChange for duplicate
    await waitFor(() => {
      expect(mockOnChange).not.toHaveBeenCalled();
    });
  });

  it("does not add empty values", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const addButton = screen.getByText("Add");
    fireEvent.click(addButton);

    expect(mockOnChange).not.toHaveBeenCalled();
  });

  it("removes chip when delete is clicked", async () => {
    const fieldWithValues = {
      ...defaultField,
      ProValue: "value1,value2",
    };

    render(
      <DynamicListTypeInput
        field={fieldWithValues}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    // Find and click the delete button for value1
    const chip = screen.getByText("value1").closest(".MuiChip-root");
    const deleteButton = chip.querySelector(".MuiChip-deleteIcon");
    fireEvent.click(deleteButton);

    expect(mockOnChange).toHaveBeenCalledWith(["value2"]);
  });

  it("disables input and button when disabled prop is true", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={true}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    expect(input).toBeDisabled();

    const addButton = screen.getByText("Add");
    expect(addButton).toBeDisabled();
  });

  it("shows helperText when provided", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText="Helper message"
      />
    );

    expect(screen.getByText("Helper message")).toBeInTheDocument();
  });


  it("handles input change", async () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "test" } });

    expect(input.value).toBe("test");
  });

  it("validates pattern when pattern is provided", async () => {
    const fieldWithPattern = {
      ...defaultField,
      Pattern: "^[a-z]+$",
      ErrorText: "Only lowercase letters allowed",
    };

    render(
      <DynamicListTypeInput
        field={fieldWithPattern}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    
    // Valid input
    fireEvent.change(input, { target: { value: "valid" } });
    
    await waitFor(() => {
      expect(screen.queryByText("Only lowercase letters allowed")).not.toBeInTheDocument();
    });
  });

  it("shows external error prop", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={true}
        helperText="External error"
      />
    );

    expect(screen.getByText("External error")).toBeInTheDocument();
    // TextField should show error state
    const input = screen.getByLabelText(/Test Label/i);
    expect(input.closest('.MuiTextField-root').querySelector('.Mui-error')).toBeInTheDocument();
  });

  it("uses default placeholder when not provided", () => {
    const fieldWithoutPlaceholder = {
      ...defaultField,
      Placeholder: undefined,
    };

    render(
      <DynamicListTypeInput
        field={fieldWithoutPlaceholder}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    expect(screen.getByPlaceholderText("Enter value")).toBeInTheDocument();
  });

  it("handles empty ProValue gracefully", () => {
    const fieldWithEmptyValue = {
      ...defaultField,
      ProValue: null,
    };

    render(
      <DynamicListTypeInput
        field={fieldWithEmptyValue}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    // Should render without chips
    expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
  });

  it("handles whitespace-only input", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "   " } });
    
    const addButton = screen.getByText("Add");
    expect(addButton).toBeDisabled();
    
    fireEvent.click(addButton);
    expect(mockOnChange).not.toHaveBeenCalled();
  });

  it("clears input and error after successful add", async () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "newvalue" } });
    
    const addButton = screen.getByText("Add");
    fireEvent.click(addButton);

    await waitFor(() => {
      expect(mockOnChange).toHaveBeenCalled();
      expect(input.value).toBe("");
    });
  });

  it("handles non-Enter key press without adding", () => {
    render(
      <DynamicListTypeInput
        field={defaultField}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const input = screen.getByLabelText(/Test Label/i);
    fireEvent.change(input, { target: { value: "test" } });
    fireEvent.keyDown(input, { key: "Tab", code: "Tab" });

    expect(mockOnChange).not.toHaveBeenCalled();
  });

  it("handles removing the last chip", async () => {
    const fieldWithOneValue = {
      ...defaultField,
      ProValue: "onlyvalue",
    };

    render(
      <DynamicListTypeInput
        field={fieldWithOneValue}
        disabled={false}
        onChange={mockOnChange}
        error={false}
        helperText=""
      />
    );

    const chip = screen.getByText("onlyvalue").closest(".MuiChip-root");
    const deleteButton = chip.querySelector(".MuiChip-deleteIcon");
    fireEvent.click(deleteButton);

    expect(mockOnChange).toHaveBeenCalledWith([]);
  });
});
