import React, { Dispatch } from "react";
import { render, screen, fireEvent, act } from "@testing-library/react-native";
import SettingsComponent from "@/components/Settings";
import { language_matrix } from "@/app/i18n/api";
import { Settings } from "@/app/lib/settings";
import { getDb } from "@/app/lib/db";
import { Knex } from "knex";

const RENDER_TIME = 1000;

jest.mock('@/app/lib/whisper', () => {
  const originalModule = jest.requireActual('@/app/lib/whisper');

  return {
    ...originalModule,
    Whisper: class {
      constructor(...args) {
        originalModule.Whisper.apply(this, args);
      }

      targetFile = {
        bytes: jest.fn().mockReturnValue(new Uint8Array([/* mock data */])),
      };
    },
  };
});

jest.mock("@/app/i18n/api", () => {
  class LanguageServer {
    fetchLanguages = () => {
      return {
        en: {
          code: "en",
          name: "English",
          targets: ["fr", "es"],
        },
        fr: {
          code: "fr",
          name: "French",
          targets: ["en", "es"],
        },
        es: {
          code: "es",
          name: "Spanish",
          targets: ["en", "fr"],
        },
      } as language_matrix;
    };
  }
  class Translator {
    translate = jest.fn((text: string, target: string) => {
      return "Hola, como estas?";
    });
  }
  return {
    LanguageServer,
    Translator,
  };
});


describe("SettingsComponent", () => {
  let db: Knex;
  let settings: Settings;

  beforeEach(async () => {
    db = await getDb("development");
    settings = new Settings(db);
    jest.spyOn(Settings, 'getDefault').mockResolvedValue(settings);
    await settings.setHostLanguage("en");
    await settings.setLibretranslateBaseUrl("https://example.com");
  });

  afterEach(async () => {
    jest.restoreAllMocks();
    await db.migrate.down();
    await db.destroy();
  });

  beforeAll(async () => {
    jest.useFakeTimers();
  });

  afterAll(() => {
    jest.useRealTimers();
  });

  test("renders correctly with initial settings", async () => {
    render(<SettingsComponent />);
    jest.advanceTimersByTime(RENDER_TIME);
    screen.debug();

    // Wait for the component to fetch and display the initial settings
    await screen.findByText(/Host Language:/i);
    await screen.findByText(/LibreTranslate Base URL:/i);

    // expect(screen.getByDisplayValue("English")).toBeTruthy();
    expect(
      screen.getByAccessibilityHint("libretranslate base url")
    ).toBeTruthy();
  });

  test("updates host language setting when input changes", async () => {
    render(<SettingsComponent />);

    // Wait for the component to fetch and display the initial settings
    await screen.findByText(/Host Language:/i);
    await screen.findByText(/LibreTranslate Base URL:/i);

    // Change the host language input value
    const picker = screen.getByAccessibilityHint("hostLanguage");
    fireEvent(picker, "onvalueChange", "es");
    expect(picker.props.selectedIndex).toStrictEqual(0);
  });

  test("updates LibreTranslate base URL setting when input changes", async () => {
    render(<SettingsComponent />);

    jest.advanceTimersByTime(RENDER_TIME);
    screen.debug();

    // Wait for the component to fetch and display the initial settings
    await screen.findByText(/Host Language:/i);
    await screen.findByText(/LibreTranslate Base URL:/i);

    // Change the LibreTranslate base URL input value
    fireEvent.changeText(
      screen.getByAccessibilityHint("libretranslate base url"),
      "http://new-example.com"
    );
    jest.advanceTimersByTime(RENDER_TIME);

    expect(
      screen.getByAccessibilityHint("libretranslate base url")
    ).toBeTruthy();
  });
});
