import { getRegisteredAccessToken } from '../tokenAccess';
import { buildPreviewRuntimeUrl, resolvePreviewAppOrigin } from '../previewRuntime';

const CHAT_EXTERNAL_LINK_OPENED_AT_KEY = 'ai-code-app.chat.external-link-opened-at';
const CHAT_EXTERNAL_LINK_TTL_MS = 15_000;
const EXTERNAL_WINDOW_TARGET_PREFIX = 'ai-code-app.external-window';
const UNSUPPORTED_STANDALONE_FALLBACK_DELAY_MS = 600;

type LinkNavigationEvent = {
  preventDefault?: () => void;
  stopPropagation?: () => void;
};

type OpenExternalLinkOptions = {
  event?: LinkNavigationEvent;
  onUnsupportedStandalone?: (url: string) => void;
  allowSameTabFallback?: boolean;
};

function canUseSessionStorage() {
  return typeof window !== 'undefined' && typeof window.sessionStorage !== 'undefined';
}

function persistExternalLinkOpenTimestamp(openedAt: number) {
  if (!canUseSessionStorage()) {
    return;
  }

  window.sessionStorage.setItem(CHAT_EXTERNAL_LINK_OPENED_AT_KEY, String(openedAt));
}

function clearExternalLinkOpenTimestamp() {
  if (!canUseSessionStorage()) {
    return;
  }

  window.sessionStorage.removeItem(CHAT_EXTERNAL_LINK_OPENED_AT_KEY);
}

function isStandaloneDisplayMode() {
  if (typeof window === 'undefined') {
    return false;
  }

  return (
    window.matchMedia?.('(display-mode: standalone)').matches === true ||
    (window.navigator as Navigator & { standalone?: boolean }).standalone === true
  );
}

function isAppleMobileStandaloneMode() {
  if (typeof window === 'undefined') {
    return false;
  }

  const navigatorValue = window.navigator as Navigator & { standalone?: boolean };
  const userAgent = navigatorValue.userAgent ?? '';
  const platform = navigatorValue.platform ?? '';
  const maxTouchPoints = typeof navigatorValue.maxTouchPoints === 'number' ? navigatorValue.maxTouchPoints : 0;
  const isAppleMobileUserAgent = /iPhone|iPad|iPod/iu.test(userAgent);
  const isTouchMac = platform === 'MacIntel' && maxTouchPoints > 1;

  return isStandaloneDisplayMode() && (isAppleMobileUserAgent || isTouchMac);
}

function buildExternalWindowTarget() {
  return `${EXTERNAL_WINDOW_TARGET_PREFIX}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
}

function openExternalWindow(url: string, target: string) {
  if (typeof window === 'undefined') {
    return null;
  }

  const openedWindow = window.open('', target);

  if (!openedWindow) {
    return null;
  }

  try {
    openedWindow.opener = null;
  } catch {
    // Ignore opener access failures in restricted runtimes.
  }

  try {
    openedWindow.location.replace(url);
  } catch {
    try {
      openedWindow.location.href = url;
    } catch {
      // Leave the popup verification fallback to handle blocked navigations.
    }
  }

  return openedWindow;
}

function clickExternalAnchor(url: string, target: string) {
  if (typeof document === 'undefined') {
    return;
  }

  const anchor = document.createElement('a');
  anchor.href = url;
  anchor.target = target;
  anchor.rel = 'noopener noreferrer';
  document.body.appendChild(anchor);
  anchor.click();
  document.body.removeChild(anchor);
}

function buildPreviewRuntimeFallbackUrl(url: string) {
  if (typeof window === 'undefined') {
    return null;
  }

  try {
    const targetUrl = new URL(url, window.location.origin);
    const previewOrigin = resolvePreviewAppOrigin();

    if (targetUrl.origin !== window.location.origin && targetUrl.origin !== previewOrigin) {
      return null;
    }

    const previewRuntimeUrl = buildPreviewRuntimeUrl(
      targetUrl.pathname,
      targetUrl.search,
      getRegisteredAccessToken(),
      null,
      'mobile',
    );

    if (!targetUrl.hash) {
      return previewRuntimeUrl;
    }

    const previewUrl = new URL(previewRuntimeUrl);
    previewUrl.hash = targetUrl.hash;
    return previewUrl.toString();
  } catch {
    return null;
  }
}

function canFallbackToSameTab(url: string) {
  if (typeof window === 'undefined') {
    return false;
  }

  try {
    const targetUrl = new URL(url, window.location.origin);
    const previewOrigin = resolvePreviewAppOrigin();
    return targetUrl.origin === window.location.origin || targetUrl.origin === previewOrigin;
  } catch {
    return false;
  }
}

function openSameTabFallback(url: string) {
  if (typeof window === 'undefined' || !canFallbackToSameTab(url)) {
    return false;
  }

  window.location.assign(url);
  return true;
}

function openPreviewRuntimeFallback(url: string) {
  if (typeof window === 'undefined') {
    return false;
  }

  const previewRuntimeUrl = buildPreviewRuntimeFallbackUrl(url);

  if (!previewRuntimeUrl) {
    return false;
  }

  window.location.assign(previewRuntimeUrl);
  return true;
}

function hasOpenedWindowNavigated(openedWindow: Window | null) {
  if (!openedWindow || openedWindow.closed) {
    return false;
  }

  try {
    return openedWindow.location.href !== 'about:blank';
  } catch {
    return true;
  }
}

function scheduleExternalWindowFallback(
  url: string,
  openedWindow: Window | null,
  allowSameTabFallback: boolean,
  callback?: (url: string) => void,
) {
  if (typeof window === 'undefined' || typeof document === 'undefined') {
    return;
  }

  window.setTimeout(() => {
    const pageStillVisible = document.visibilityState !== 'hidden';
    const pageStillFocused = typeof document.hasFocus !== 'function' || document.hasFocus();

    if (!pageStillVisible || !pageStillFocused) {
      return;
    }

    if (hasOpenedWindowNavigated(openedWindow)) {
      return;
    }

    if (allowSameTabFallback && isAppleMobileStandaloneMode()) {
      if (openPreviewRuntimeFallback(url)) {
        return;
      }
    }

    if (allowSameTabFallback && openSameTabFallback(url)) {
      return;
    }

    callback?.(url);
  }, UNSUPPORTED_STANDALONE_FALLBACK_DELAY_MS);
}

export function shouldSkipForegroundResyncAfterExternalLink() {
  if (!canUseSessionStorage()) {
    return false;
  }

  const rawOpenedAt = window.sessionStorage.getItem(CHAT_EXTERNAL_LINK_OPENED_AT_KEY);
  clearExternalLinkOpenTimestamp();

  if (!rawOpenedAt) {
    return false;
  }

  const openedAt = Number(rawOpenedAt);
  return Number.isFinite(openedAt) && Date.now() - openedAt <= CHAT_EXTERNAL_LINK_TTL_MS;
}

export function openExternalLinkInNewWindow(url: string, options: OpenExternalLinkOptions = {}) {
  options.event?.preventDefault?.();
  options.event?.stopPropagation?.();

  if (typeof window === 'undefined') {
    return;
  }

  persistExternalLinkOpenTimestamp(Date.now());
  const target = buildExternalWindowTarget();
  const allowSameTabFallback = options.allowSameTabFallback ?? true;
  const openedWindow = openExternalWindow(url, target);

  if (!openedWindow && allowSameTabFallback) {
    clickExternalAnchor(url, target);
  }

  scheduleExternalWindowFallback(url, openedWindow, allowSameTabFallback, options.onUnsupportedStandalone);
}

export function openChatExternalLink(url: string, event?: LinkNavigationEvent) {
  openExternalLinkInNewWindow(url, {
    event,
  });
}
