/**
 * @vitest-environment jsdom
 */
import React from 'react';
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { UIStateProvider } from '@alga-psa/ui/ui-reflection/UIStateContext';
import { toast } from 'react-hot-toast';

import ExperimentalFeaturesSettings from '../../../components/settings/general/ExperimentalFeaturesSettings';
import { canEnableAiAssistant, getExperimentalFeatures, updateExperimentalFeatures } from '@alga-psa/tenancy/actions';

const translationMap: Record<string, string> = {
  'experimentalFeatures.loading': 'Loading experimental features...',
  'experimentalFeatures.title': 'Experimental Features',
  'experimentalFeatures.description': 'Enable or disable experimental features for your tenant.',
  'experimentalFeatures.alert.title': 'Experimental',
  'experimentalFeatures.alert.description': 'Experimental features may change or be removed without notice.',
  'experimentalFeatures.features.aiAssistant.name': 'AI Assistant',
  'experimentalFeatures.features.aiAssistant.description': 'Enable AI-powered Quick Ask and Chat sidebar.',
  'experimentalFeatures.features.aiAssistant.restriction': 'Only available for whitelisted tenants.',
  'experimentalFeatures.actions.save': 'Save',
  'experimentalFeatures.actions.saving': 'Saving...',
  'experimentalFeatures.actions.retry': 'Retry',
  'experimentalFeatures.messages.success.saved':
    'Experimental feature settings saved. Reload the page to apply changes.',
  'experimentalFeatures.messages.error.loadFailed': 'Failed to load experimental feature settings.',
  'experimentalFeatures.messages.error.saveFailed': 'Failed to save experimental feature settings.',
};

const translate = (key: string): string => translationMap[key] ?? key;

vi.mock('@alga-psa/tenancy/actions', () => ({
  getExperimentalFeatures: vi.fn().mockResolvedValue({ aiAssistant: false }),
  canEnableAiAssistant: vi.fn().mockResolvedValue(true),
  updateExperimentalFeatures: vi.fn(),
}));

vi.mock('@alga-psa/ui/lib/i18n/client', () => ({
  useTranslation: () => ({
    t: translate,
  }),
}));

vi.mock('react-hot-toast', () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn(),
  },
}));

describe('ExperimentalFeaturesSettings', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  afterEach(() => {
    cleanup();
  });

  it("shows 'AI Assistant' name and description", async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    expect(await screen.findByText('AI Assistant')).toBeInTheDocument();
    expect(
      screen.getByText('Enable AI-powered Quick Ask and Chat sidebar.')
    ).toBeInTheDocument();
  });

  it('defaults AI Assistant toggle to off', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({} as any);

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el!;
    });

    expect(toggle.getAttribute('aria-checked')).toBe('false');
  });

  it('renders experimental features warning banner', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    expect(await screen.findByText('Experimental')).toBeInTheDocument();
    expect(
      screen.getByText('Experimental features may change or be removed without notice.')
    ).toBeInTheDocument();
  });

  it('calls updateExperimentalFeatures() with current toggle states on save', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });
    vi.mocked(updateExperimentalFeatures).mockResolvedValueOnce(undefined);

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el!;
    });

    fireEvent.click(toggle);

    const saveButton = await screen.findByRole('button', { name: 'Save' });
    await waitFor(() => {
      expect(saveButton).not.toBeDisabled();
    });
    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(updateExperimentalFeatures).toHaveBeenCalledWith({ aiAssistant: true });
    });
  });

  it('shows success feedback after saving', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });
    vi.mocked(updateExperimentalFeatures).mockResolvedValueOnce(undefined);

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el!;
    });

    fireEvent.click(toggle);

    const saveButton = await screen.findByRole('button', { name: 'Save' });
    await waitFor(() => {
      expect(saveButton).not.toBeDisabled();
    });
    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(vi.mocked(toast.success)).toHaveBeenCalledWith(
        'Experimental feature settings saved. Reload the page to apply changes.'
      );
    });
  });

  it('updates local state when toggled', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el!;
    });

    expect(toggle.getAttribute('aria-checked')).toBe('false');
    fireEvent.click(toggle);
    expect(toggle.getAttribute('aria-checked')).toBe('true');
  });

  it('loads current settings on mount', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: true });

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el;
    });

    expect(toggle.getAttribute('aria-checked')).toBe('true');
  });

  it('renders list of features with toggles', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(true);
    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    await waitFor(() => {
      expect(getExperimentalFeatures).toHaveBeenCalledTimes(1);
    });

    const toggle = document.querySelector(
      '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
    );
    expect(toggle).toBeTruthy();
    expect(screen.queryByText('Workflow Automation')).not.toBeInTheDocument();
    expect(screen.getAllByRole('switch')).toHaveLength(1);
  });

  it('disables AI Assistant toggle when not allowed', async () => {
    vi.mocked(canEnableAiAssistant).mockResolvedValueOnce(false);
    vi.mocked(getExperimentalFeatures).mockResolvedValueOnce({ aiAssistant: false });

    render(
      <UIStateProvider
        initialPageState={{
          id: 'test-page',
          title: 'Test Page',
          components: [],
        }}
      >
        <ExperimentalFeaturesSettings />
      </UIStateProvider>
    );

    const toggle = await waitFor(() => {
      const el = document.querySelector(
        '[data-automation-id="experimental-feature-toggle-aiAssistant"]'
      ) as HTMLElement | null;
      expect(el).toBeTruthy();
      return el!;
    });

    expect(toggle.getAttribute('aria-checked')).toBe('false');
    fireEvent.click(toggle);
    expect(toggle.getAttribute('aria-checked')).toBe('false');
    expect(await screen.findByText('Only available for whitelisted tenants.')).toBeInTheDocument();
  });
});
