import { afterEach, describe, expect, it, vi } from 'vitest';
import {
  insideTelegram,
  routeExternalLinkInTelegram,
  telegramClosingConfirmation,
  telegramLaunch,
  telegramOpenExternalLink,
  telegramRequestFullscreen,
} from './telegram';

function stubWebApp(initData: string, startParam?: string) {
  vi.stubGlobal('window', {
    Telegram: {
      WebApp: {
        initData,
        initDataUnsafe: startParam ? { start_param: startParam } : {},
        themeParams: { bg_color: '#101418' },
        ready: () => {},
        expand: () => {},
      },
    },
  });
}

describe('telegram launch detection', () => {
  afterEach(() => vi.unstubAllGlobals());

  it('is not inside Telegram without a window', () => {
    expect(insideTelegram()).toBe(false);
  });

  it('is inside Telegram only with non-empty initData', () => {
    stubWebApp('');
    expect(insideTelegram()).toBe(false);
    stubWebApp('query_id=abc');
    expect(insideTelegram()).toBe(true);
  });

  it('telegramLaunch returns initData, start param and theme', () => {
    stubWebApp('query_id=abc', 'g123');
    const launch = telegramLaunch();
    expect(launch.initData).toBe('query_id=abc');
    expect(launch.startParam).toBe('g123');
    expect(launch.theme?.bg_color).toBe('#101418');
  });
});

// stubClient stands up a fake WebApp on the given platform with spies for the mobile-gated
// chrome toggles, so the platform gate can be asserted without a real Telegram client.
function stubClient(platform?: string) {
  const enable = vi.fn();
  const disable = vi.fn();
  const requestFullscreen = vi.fn();
  vi.stubGlobal('window', {
    Telegram: {
      WebApp: { platform, enableClosingConfirmation: enable, disableClosingConfirmation: disable, requestFullscreen },
    },
  });
  return { enable, disable, requestFullscreen };
}

const mobilePlatforms = ['ios', 'android', 'android_x'];
const desktopPlatforms = ['tdesktop', 'macos', 'web', undefined];

describe('telegramClosingConfirmation', () => {
  afterEach(() => vi.unstubAllGlobals());

  it('arms the close guard on mobile clients', () => {
    for (const p of mobilePlatforms) {
      const { enable } = stubClient(p);
      telegramClosingConfirmation(true);
      expect(enable, `platform=${p}`).toHaveBeenCalledOnce();
    }
  });

  it('skips the close guard on desktop clients (the dialog there is just noise)', () => {
    for (const p of desktopPlatforms) {
      const { enable } = stubClient(p);
      telegramClosingConfirmation(true);
      expect(enable, `platform=${p}`).not.toHaveBeenCalled();
    }
  });

  it('always lifts the guard on leave, regardless of platform', () => {
    const { disable } = stubClient('tdesktop');
    telegramClosingConfirmation(false);
    expect(disable).toHaveBeenCalledOnce();
  });
});

describe('telegramRequestFullscreen', () => {
  afterEach(() => vi.unstubAllGlobals());

  it('goes immersive fullscreen on mobile clients', () => {
    for (const p of mobilePlatforms) {
      const { requestFullscreen } = stubClient(p);
      telegramRequestFullscreen();
      expect(requestFullscreen, `platform=${p}`).toHaveBeenCalledOnce();
    }
  });

  it('leaves desktop clients as a standard window (the bot full-size setting fills it)', () => {
    for (const p of desktopPlatforms) {
      const { requestFullscreen } = stubClient(p);
      telegramRequestFullscreen();
      expect(requestFullscreen, `platform=${p}`).not.toHaveBeenCalled();
    }
  });
});

describe('telegramOpenExternalLink', () => {
  afterEach(() => vi.unstubAllGlobals());

  it('routes an external URL through the SDK openLink inside Telegram', () => {
    const openLink = vi.fn();
    vi.stubGlobal('window', { Telegram: { WebApp: { openLink } } });
    expect(telegramOpenExternalLink('https://gramota.ru/poisk?query=кот')).toBe(true);
    expect(openLink).toHaveBeenCalledWith('https://gramota.ru/poisk?query=кот');
  });

  it('returns false without the SDK so the caller falls back to the anchor', () => {
    expect(telegramOpenExternalLink('https://x.io')).toBe(false);
  });
});

describe('routeExternalLinkInTelegram', () => {
  afterEach(() => vi.unstubAllGlobals());

  function stubInside(openLink = vi.fn(), origin = 'https://app.example') {
    vi.stubGlobal('window', { Telegram: { WebApp: { initData: 'query_id=abc', openLink } } });
    vi.stubGlobal('location', { href: origin + '/', origin });
    return openLink;
  }

  it('routes an external http(s) _blank link through openLink inside Telegram', () => {
    const openLink = stubInside();
    expect(routeExternalLinkInTelegram({ href: 'https://gramota.ru/poisk?query=кот', target: '_blank' })).toBe(true);
    expect(openLink).toHaveBeenCalledWith('https://gramota.ru/poisk?query=кот');
  });

  it('leaves a t.me link to the native handler (openTelegramLink owns those)', () => {
    const openLink = stubInside();
    expect(routeExternalLinkInTelegram({ href: 'https://t.me/some_bot', target: '_blank' })).toBe(false);
    expect(openLink).not.toHaveBeenCalled();
  });

  it('leaves same-origin and non-_blank links to in-app navigation', () => {
    const openLink = stubInside(vi.fn(), 'https://app.example');
    expect(routeExternalLinkInTelegram({ href: 'https://app.example/lobby', target: '_blank' })).toBe(false);
    expect(routeExternalLinkInTelegram({ href: 'https://gramota.ru', target: '' })).toBe(false);
    expect(openLink).not.toHaveBeenCalled();
  });

  it('does nothing outside Telegram (the anchor opens natively)', () => {
    expect(routeExternalLinkInTelegram({ href: 'https://x.io', target: '_blank' })).toBe(false);
  });
});
