import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UpdateSettings } from '@/components/settings/UpdateSettings';
import { useUpdateStore } from '@/stores/update';

const actionableMessage =
  '\u5f53\u524d\u5e73\u53f0\u7684\u6b63\u5f0f\u66f4\u65b0\u5305\u5c1a\u672a\u53d1\u5e03\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002';

vi.mock('react-i18next', async (importOriginal) => {
  const actual = await importOriginal<typeof import('react-i18next')>();
  return {
    ...actual,
    useTranslation: () => ({
      t: (key: string) =>
        ({
          'updates.currentVersion': 'Current version',
          'updates.status.failed': 'Generic update failure',
          'updates.action.retry': 'Retry',
        })[key] ?? key,
    }),
  };
});

describe('UpdateSettings update errors', () => {
  const init = vi.fn().mockResolvedValue(undefined);
  const checkForUpdates = vi.fn().mockResolvedValue(undefined);
  const clearError = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    useUpdateStore.setState({
      status: 'error',
      currentVersion: '1.0.0',
      updateInfo: null,
      progress: null,
      error: actionableMessage,
      isInitialized: true,
      isInitializing: false,
      autoInstallCountdown: null,
      init,
      checkForUpdates,
      clearError,
    });
  });

  it('shows a concise updater error only once', () => {
    render(<UpdateSettings />);

    expect(screen.getAllByText(actionableMessage)).toHaveLength(1);
  });

  it.each([
    'Cannot find channel "latest.yml" update info: HttpError: 404\r\nPlease double check authentication\r\n    at ElectronHttpExecutor.handleResponse (app.asar/node_modules/builder-util-runtime/out/httpExecutor.js:121:20)',
    'Cannot find channel "latest.yml" update info: HttpError: 404\\r\\nPlease double check authentication\\n    at ElectronHttpExecutor.handleResponse (app.asar/node_modules/builder-util-runtime/out/httpExecutor.js:121:20)',
  ])('does not expose updater stack details for a long technical error', (error) => {
    useUpdateStore.setState({ error });

    render(<UpdateSettings />);

    expect(screen.getByText('Generic update failure')).toBeInTheDocument();
    expect(screen.queryByText(/ElectronHttpExecutor|node_modules|Please double check/)).not.toBeInTheDocument();
    expect(screen.queryByText('updates.errorDetails')).not.toBeInTheDocument();
  });

  it.each([
    'net::ERR_NAME_NOT_RESOLVED',
    'Error: Update check failed',
    'Update check temporarily unavailable',
    "ENOENT: no such file or directory, open 'C:\\Users\\tester\\AppData\\Local\\Makelore\\latest.yml'",
    'ERR_UPDATER_INVALID_RELEASE_FEED',
    '{"code":"ERR_UPDATER_INVALID_RELEASE_FEED","message":"Update check failed"}',
  ])('falls back for a short technical updater diagnostic: %s', (error) => {
    useUpdateStore.setState({ error });

    render(<UpdateSettings />);

    expect(screen.getByText('Generic update failure')).toBeInTheDocument();
    expect(screen.queryByText(error)).not.toBeInTheDocument();
  });

  it('keeps concise actionable Chinese prose', () => {
    render(<UpdateSettings />);

    expect(screen.getByText(actionableMessage)).toBeInTheDocument();
  });

  it('initializes on mount and retries through the existing store action', async () => {
    render(<UpdateSettings />);

    await waitFor(() => expect(init).toHaveBeenCalledTimes(1));
    fireEvent.click(screen.getByRole('button', { name: 'Retry' }));

    await waitFor(() => expect(checkForUpdates).toHaveBeenCalledTimes(1));
    expect(clearError).toHaveBeenCalledTimes(1);
  });
});
