import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import ErrorBoundary from '@/components/ErrorBoundary';

// Komponen yang sengaja throw error saat render
const BrokenComponent = () => {
  throw new Error('Test error boundary!');
};

// Komponen normal
const NormalComponent = () => <></>;

// Suppress React's error boundary console output selama test

beforeEach(() => {
  jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
  (console.error as jest.Mock).mockRestore();
});

describe('ErrorBoundary', () => {
  it('merender children dengan normal jika tidak ada error', () => {
    // Tidak boleh throw dan tidak menampilkan teks error
    const { queryByText } = render(
      <ErrorBoundary>
        <NormalComponent />
      </ErrorBoundary>
    );
    expect(queryByText('Terjadi Kesalahan')).toBeNull();
  });

  it('menampilkan UI fallback ketika child throw error', () => {
    const { getByText } = render(
      <ErrorBoundary>
        <BrokenComponent />
      </ErrorBoundary>
    );
    expect(getByText('Terjadi Kesalahan')).toBeTruthy();
  });

  it('menampilkan pesan error yang dilempar', () => {
    const { getByText } = render(
      <ErrorBoundary>
        <BrokenComponent />
      </ErrorBoundary>
    );
    expect(getByText('Test error boundary!')).toBeTruthy();
  });

  it('merender custom fallback jika prop fallback diberikan', () => {
    const { getByText } = render(
      <ErrorBoundary fallback={<></>}>
        <BrokenComponent />
      </ErrorBoundary>
    );
    // Custom fallback fragment kosong — pastikan teks default tidak muncul
    expect(() => getByText('Terjadi Kesalahan')).toThrow();
  });

  it('mereset error state saat tombol Coba Lagi ditekan', () => {
    const { getByText } = render(
      <ErrorBoundary>
        <BrokenComponent />
      </ErrorBoundary>
    );

    const button = getByText('Coba Lagi');
    expect(button).toBeTruthy();

    // Tekan tombol reset — hasError kembali false, BrokenComponent throw lagi
    // sehingga fallback muncul kembali (membuktikan reset berjalan)
    fireEvent.press(button);
    expect(getByText('Terjadi Kesalahan')).toBeTruthy();
  });
});
