import { render, screen, fireEvent } from "@testing-library/react";
import { DigitalClock } from "../containers/DigitalClock";
import * as utils from "../utils";

vi.mock("../utils");

const mockedDateToDigital = vi.mocked(utils.dateToDigital);
const mockedDigitalToDate = vi.mocked(utils.digitalToDate);

describe("DigitalClock", () => {
  const onTimeChangeMock = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    mockedDateToDigital.mockReturnValue("14:30:15");
    mockedDigitalToDate.mockImplementation((str: string) => {
      const parts = str.split(":");
      if (parts.length !== 3) return new Date(NaN);
      const [h, m, s] = parts.map(Number);
      if (isNaN(h) || isNaN(m) || isNaN(s)) return new Date(NaN);
      const d = new Date(2025, 0, 1, 14, 30, 15);
      d.setHours(h, m, s, 0);
      return d;
    });
  });

  it("renders the input as disabled when disabled prop is true", () => {
    render(
      <DigitalClock
        disabled={true}
        currentTime={new Date(2025, 0, 1, 14, 30, 15)}
        onTimeChange={onTimeChangeMock}
      />,
    );
    const input = screen.getByTestId("time-input");
    expect(input).toBeDisabled();
  });

  it("renders the input with the correct initial value when enabled", () => {
    render(
      <DigitalClock
        currentTime={new Date(2025, 0, 1, 14, 30, 15)}
        onTimeChange={onTimeChangeMock}
      />,
    );
    const input = screen.getByTestId("time-input") as HTMLInputElement;
    expect(input).toBeInTheDocument();
    expect(input.value).toBe("14:30:15");
  });

  it("calls onTimeChange when a valid time is entered", () => {
    render(
      <DigitalClock
        currentTime={new Date(2025, 0, 1, 14, 30, 15)}
        onTimeChange={onTimeChangeMock}
      />,
    );
    const input = screen.getByTestId("time-input");
    fireEvent.change(input, { target: { value: "12:00:00" } });

    expect(onTimeChangeMock).toHaveBeenCalledTimes(1);
    const expectedDate = new Date(2025, 0, 1, 12, 0, 0, 0);
    expect(onTimeChangeMock).toHaveBeenCalledWith(expectedDate);

    expect(input).toHaveValue("12:00:00");
  });

  it("does not call onTimeChange when an invalid time is entered", () => {
    render(
      <DigitalClock
        currentTime={new Date(2025, 0, 1, 14, 30, 15)}
        onTimeChange={onTimeChangeMock}
      />,
    );
    const input = screen.getByTestId("time-input");
    fireEvent.change(input, { target: { value: "notatime" } });
    expect(onTimeChangeMock).not.toHaveBeenCalled();
    expect(input).toHaveValue("notatime");
  });
});
