import React from "react";
import { render, fireEvent, waitFor, act } from "@testing-library/react-native";

const mockFs = { saveSignatureBase64ToPermanentFile: jest.fn() };
const mockSigState = {
  lastOnOK: null as null | ((data: string) => void),
  lastOnEmpty: null as null | (() => void),
};

jest.mock("react-native-signature-canvas", () => {
  const ReactLocal = require("react");
  const { View } = require("react-native");
  function SignatureCanvas(
    props: { onOK?: (d: string) => void; onEmpty?: () => void },
    ref: React.Ref<{ readSignature: () => void }>
  ) {
    mockSigState.lastOnOK = props.onOK ?? null;
    mockSigState.lastOnEmpty = (props as { onEmpty?: () => void }).onEmpty ?? null;
    ReactLocal.useImperativeHandle(ref, () => ({
      readSignature: () => props.onOK && props.onOK("data:image/png;base64,ABC"),
    }));
    return ReactLocal.createElement(View, null);
  }
  return {
    __esModule: true,
    default: ReactLocal.forwardRef(SignatureCanvas),
  };
});

jest.mock("../../src/core/fileStorage", () => ({
  saveSignatureBase64ToPermanentFile: (...args: unknown[]) =>
    mockFs.saveSignatureBase64ToPermanentFile(...args),
}));

import SignatureCapture from "../../src/shared/SignatureCapture";

describe("SignatureCapture", () => {
  beforeEach(() => {
    mockFs.saveSignatureBase64ToPermanentFile.mockReset();
    mockSigState.lastOnOK = null;
  });

  const defaultProps = {
    interventionId: 1,
    stepId: "s1",
    brandColor: "#1E56A8",
    onCaptured: jest.fn(),
  };

  it("affiche le bouton 'Signer'", () => {
    const { getByText } = render(<SignatureCapture {...defaultProps} onCaptured={jest.fn()} />);
    expect(getByText("Signer")).toBeTruthy();
  });

  it("ouvre le modal au clic sur Signer", async () => {
    const { getByText } = render(<SignatureCapture {...defaultProps} onCaptured={jest.fn()} />);
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    expect(getByText("Enregistrer")).toBeTruthy();
  });

  it("Annuler ferme", async () => {
    const { getByText, queryByText } = render(
      <SignatureCapture {...defaultProps} onCaptured={jest.fn()} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    await act(async () => {
      fireEvent.press(getByText("Annuler"));
    });
    expect(queryByText("Enregistrer")).toBeNull();
  });

  it("Modal onRequestClose ferme", async () => {
    const { getByText, UNSAFE_getByType, queryByText } = render(
      <SignatureCapture {...defaultProps} onCaptured={jest.fn()} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    const { Modal } = require("react-native");
    const modal = UNSAFE_getByType(Modal);
    await act(async () => {
      modal.props.onRequestClose();
    });
    expect(queryByText("Enregistrer")).toBeNull();
  });

  it("Enregistrer lit la signature -> onCaptured + ferme", async () => {
    mockFs.saveSignatureBase64ToPermanentFile.mockResolvedValue("file:///sig.png");
    const onCaptured = jest.fn();
    const { getByText, queryByText } = render(
      <SignatureCapture {...defaultProps} onCaptured={onCaptured} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    await act(async () => {
      fireEvent.press(getByText("Enregistrer"));
    });
    await waitFor(() => expect(onCaptured).toHaveBeenCalledWith("file:///sig.png"));
    expect(mockFs.saveSignatureBase64ToPermanentFile).toHaveBeenCalledWith(
      1,
      "s1",
      "ABC"
    );
    expect(queryByText("Enregistrer")).toBeNull();
  });

  it("onOK handle sans prefixe data:image/... (pas de marker)", async () => {
    mockFs.saveSignatureBase64ToPermanentFile.mockResolvedValue("file:///sig.png");
    const onCaptured = jest.fn();
    const { getByText } = render(
      <SignatureCapture {...defaultProps} onCaptured={onCaptured} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    // Call onOK directly without base64 prefix marker
    await act(async () => {
      mockSigState.lastOnOK?.("RAWBASE64NOPREFIX");
    });
    await waitFor(() =>
      expect(mockFs.saveSignatureBase64ToPermanentFile).toHaveBeenCalledWith(
        1,
        "s1",
        "RAWBASE64NOPREFIX"
      )
    );
  });

  it("saving pendant -> ActivityIndicator rendu + disabled style", async () => {
    let resolveSave: (v: string) => void = () => {};
    mockFs.saveSignatureBase64ToPermanentFile.mockImplementation(
      () => new Promise((r) => { resolveSave = r; })
    );
    const { getByText, queryByText, UNSAFE_getByType } = render(
      <SignatureCapture {...defaultProps} onCaptured={jest.fn()} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    // Trigger saving via onOK
    await act(async () => {
      mockSigState.lastOnOK?.("data:image/png;base64,X");
    });
    // Pending : ActivityIndicator devrait etre rendu
    const { ActivityIndicator } = require("react-native");
    expect(UNSAFE_getByType(ActivityIndicator)).toBeTruthy();
    expect(queryByText("Enregistrer")).toBeNull();
    await act(async () => {
      resolveSave("file:///s.png");
    });
  });

  it("onEmpty est une no-op invocable", async () => {
    const { getByText } = render(
      <SignatureCapture {...defaultProps} onCaptured={jest.fn()} />
    );
    await act(async () => {
      fireEvent.press(getByText("Signer"));
    });
    expect(() => mockSigState.lastOnEmpty?.()).not.toThrow();
  });
});
