/**
 * RED test scaffold: components/InstallPrompt.tsx — iOS/Android install prompt (PWA-01, PWA-02)
 *
 * Behaviors under test:
 *   1. isIOSSafariNonStandalone() returns true for a mock iOS Safari non-standalone UA
 *   2. isIOSSafariNonStandalone() returns false when running in standalone mode
 *   3. useAndroidInstallPrompt sets canInstall=true when a mock beforeinstallprompt event fires
 *   4. useAndroidInstallPrompt sets canInstall=false when appinstalled event fires
 *
 * These tests FAIL (RED) because components/InstallPrompt.tsx does not exist yet.
 * They will turn GREEN in Plan 03-06 when the implementation is added.
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { renderHook, act } from '@testing-library/react';

// This import fails (RED) — InstallPrompt.tsx does not exist yet.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore intentional RED import
import { isIOSSafariNonStandalone, useAndroidInstallPrompt } from './InstallPrompt.js';

// Capture the original navigator descriptors so we can restore them
const originalUserAgent = navigator.userAgent;

function setUserAgent(ua: string) {
  Object.defineProperty(navigator, 'userAgent', {
    value: ua,
    writable: true,
    configurable: true,
  });
}

function setStandalone(value: boolean) {
  // navigator.standalone is an iOS-only property
  Object.defineProperty(navigator, 'standalone', {
    value,
    writable: true,
    configurable: true,
  });
}

describe('isIOSSafariNonStandalone', () => {
  afterEach(() => {
    // Restore original userAgent
    Object.defineProperty(navigator, 'userAgent', {
      value: originalUserAgent,
      writable: true,
      configurable: true,
    });
    // Remove standalone mock
    Object.defineProperty(navigator, 'standalone', {
      value: undefined,
      writable: true,
      configurable: true,
    });
  });

  it('returns true for an iOS Safari non-standalone UA', () => {
    setUserAgent(
      'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X) ' +
        'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1',
    );
    setStandalone(false);

    expect(isIOSSafariNonStandalone()).toBe(true);
  });

  it('returns false when running in standalone mode (PWA installed)', () => {
    setUserAgent(
      'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X) ' +
        'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1',
    );
    setStandalone(true);

    expect(isIOSSafariNonStandalone()).toBe(false);
  });

  it('returns false for an Android Chrome UA', () => {
    setUserAgent(
      'Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 ' +
        '(KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36',
    );
    setStandalone(false);

    expect(isIOSSafariNonStandalone()).toBe(false);
  });
});

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

  it('sets canInstall=true when a beforeinstallprompt event is dispatched', () => {
    const { result } = renderHook(() => useAndroidInstallPrompt());
    expect(result.current.canInstall).toBe(false);

    const mockPromptEvent = new Event('beforeinstallprompt') as Event & {
      prompt: () => Promise<void>;
      userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
    };
    mockPromptEvent.prompt = vi.fn().mockResolvedValue(undefined);
    mockPromptEvent.userChoice = Promise.resolve({ outcome: 'accepted' });

    act(() => {
      window.dispatchEvent(mockPromptEvent);
    });

    expect(result.current.canInstall).toBe(true);
  });

  it('sets canInstall=false when appinstalled event fires', () => {
    const { result } = renderHook(() => useAndroidInstallPrompt());

    // First fire beforeinstallprompt to set canInstall=true
    const mockPromptEvent = new Event('beforeinstallprompt') as Event & {
      prompt: () => Promise<void>;
      userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
    };
    mockPromptEvent.prompt = vi.fn().mockResolvedValue(undefined);
    mockPromptEvent.userChoice = Promise.resolve({ outcome: 'dismissed' });

    act(() => {
      window.dispatchEvent(mockPromptEvent);
    });

    expect(result.current.canInstall).toBe(true);

    // Now fire appinstalled — should reset canInstall to false
    act(() => {
      window.dispatchEvent(new Event('appinstalled'));
    });

    expect(result.current.canInstall).toBe(false);
  });
});
