'use client';

import { usePathname } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';

interface BeforeInstallPromptEvent extends Event {
  prompt: () => Promise<void>;
  userChoice: Promise<{ outcome: 'accepted' | 'dismissed'; platform: string }>;
}

const DISMISS_STORAGE_KEY = 'pz-install-prompt-dismissed-at';
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;

const CONVERSION_PATH_PATTERNS = ['/basket', '/orders/'];

const IN_APP_BROWSER_PATTERN =
  /FBAN|FBAV|FB_IAB|Instagram|Twitter|Line\/|LinkedInApp|TikTok|Snapchat|; wv\)/i;
const NON_SAFARI_IOS_PATTERN = /CriOS|FxiOS|EdgiOS|OPiOS|YaBrowser|UCBrowser/i;

const safeRead = (key: string): string | null => {
  try {
    return window.localStorage.getItem(key);
  } catch {
    return null;
  }
};

const safeWrite = (key: string, value: string): void => {
  try {
    window.localStorage.setItem(key, value);
  } catch {
    // Safari Private Mode, quota exceeded — fail soft
  }
};

const isWithinDismissWindow = (timestamp: string | null): boolean => {
  if (!timestamp) return false;
  const dismissedAt = Number(timestamp);
  if (!Number.isFinite(dismissedAt)) return false;
  return Date.now() - dismissedAt < SEVEN_DAYS_MS;
};

const detectIOS = (): boolean => {
  const ua = window.navigator.userAgent;
  const isAppleMobile = /iPad|iPhone|iPod/.test(ua);
  // iPadOS 13+ reports as Macintosh; disambiguate via touch points
  const isIPadOSAsMac = /Mac/.test(ua) && navigator.maxTouchPoints > 1;
  const isMSStream = !!(window as Window & { MSStream?: unknown }).MSStream;
  return (isAppleMobile || isIPadOSAsMac) && !isMSStream;
};

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

const detectInAppBrowser = (): boolean =>
  IN_APP_BROWSER_PATTERN.test(window.navigator.userAgent);

const detectNonSafariIOSBrowser = (): boolean =>
  NON_SAFARI_IOS_PATTERN.test(window.navigator.userAgent);

const isConversionPath = (pathname: string): boolean =>
  CONVERSION_PATH_PATTERNS.some((pattern) => pathname.includes(pattern));

export const useInstallPrompt = () => {
  const pathname = usePathname() ?? '';

  const [isHydrated, setIsHydrated] = useState(false);
  const [deferredPrompt, setDeferredPrompt] =
    useState<BeforeInstallPromptEvent | null>(null);
  const [isIOS, setIsIOS] = useState(false);
  const [isStandalone, setIsStandalone] = useState(false);
  const [isInAppBrowser, setIsInAppBrowser] = useState(false);
  const [isNonSafariIOS, setIsNonSafariIOS] = useState(false);
  const [isDismissed, setIsDismissed] = useState(false);

  useEffect(() => {
    setIsStandalone(detectStandalone());
    setIsIOS(detectIOS());
    setIsInAppBrowser(detectInAppBrowser());
    setIsNonSafariIOS(detectNonSafariIOSBrowser());
    setIsDismissed(isWithinDismissWindow(safeRead(DISMISS_STORAGE_KEY)));
    setIsHydrated(true);

    const handleBeforeInstallPrompt = (event: Event) => {
      event.preventDefault();
      setDeferredPrompt(event as BeforeInstallPromptEvent);
    };

    const handleAppInstalled = () => {
      setDeferredPrompt(null);
      setIsStandalone(true);
    };

    const handleStorageChange = (event: StorageEvent) => {
      if (event.key !== DISMISS_STORAGE_KEY) return;
      setIsDismissed(isWithinDismissWindow(event.newValue));
    };

    window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
    window.addEventListener('appinstalled', handleAppInstalled);
    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener(
        'beforeinstallprompt',
        handleBeforeInstallPrompt
      );
      window.removeEventListener('appinstalled', handleAppInstalled);
      window.removeEventListener('storage', handleStorageChange);
    };
  }, []);

  const dismiss = useCallback(() => {
    safeWrite(DISMISS_STORAGE_KEY, Date.now().toString());
    setIsDismissed(true);
  }, []);

  const install = useCallback(async () => {
    if (!deferredPrompt) return null;
    await deferredPrompt.prompt();
    const { outcome } = await deferredPrompt.userChoice;
    if (outcome === 'accepted') {
      setDeferredPrompt(null);
    } else {
      dismiss();
    }
    return outcome;
  }, [deferredPrompt, dismiss]);

  const canInstall =
    isHydrated &&
    !isStandalone &&
    !isDismissed &&
    !isInAppBrowser &&
    !isConversionPath(pathname) &&
    (deferredPrompt !== null || (isIOS && !isNonSafariIOS));

  return {
    canInstall,
    isIOS,
    isStandalone,
    install,
    dismiss
  };
};
