import { Tag } from 'antd';
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import './AppsLibraryView.css';
import { BaseballTicketBayPlayAppView } from '../baseball-ticket-bay/BaseballTicketBayPlayAppView';
import { EReaderAppView } from '../e-reader/EReaderAppView';
import { PhotoPrismAppView } from '../photoprism/PhotoPrismAppView';
import { PhotoPuzzleAppView } from '../photo-puzzle/PhotoPuzzleAppView';
import { TheQuestAppView } from '../the-quest/TheQuestAppView';
import { TetrisAppView } from '../tetris/TetrisAppView';
import { Template1PlayAppView } from '../template1/Template1PlayAppView';
import {
  getCurrentPlayAppEnvironment,
  getPlayAppEntries,
  isPlayAppLaunchableInEnvironment,
  loadPlayAppEntriesFromServer,
} from './appsRegistry';
import { buildPlayAppPath } from '../../../../app/main/routes';
import { createInstallManifestObjectUrl, swapInstallDocumentMetadata } from '../../../../app/main/pwa/installManifest';

function normalizeReturnToPath(returnTo: string | null) {
  if (!returnTo || !returnTo.startsWith('/') || returnTo.startsWith('//')) {
    return null;
  }

  return returnTo;
}

function resolvePlayAppInstallThemeColor(appId: string) {
  switch (appId) {
    case 'baseball-ticket-bay':
      return '#1b3f91';
    case 'photoprism':
      return '#0f766e';
    case 'photo-puzzle':
      return '#d97706';
    case 'the-quest':
      return '#7c3aed';
    case 'template1':
      return '#2f8dff';
    case 'tetris':
      return '#0f172a';
    default:
      return '#165dff';
  }
}

export function AppsLibraryView() {
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const [isCompactViewport, setIsCompactViewport] = useState(() =>
    typeof window === 'undefined' ? false : window.matchMedia('(max-width: 768px)').matches,
  );
  const [playAppEntries, setPlayAppEntries] = useState(() => getPlayAppEntries());
  const [isLoadingPlayApps, setIsLoadingPlayApps] = useState(false);
  const activeAppId = searchParams.get('app');
  const launchContext = searchParams.get('launchContext') === 'embedded' ? 'embedded' : 'direct';
  const returnTo = normalizeReturnToPath(searchParams.get('returnTo'));
  const environment = getCurrentPlayAppEnvironment();
  const activeAppEntry = useMemo(() => {
    const candidate = playAppEntries.find((entry) => entry.id === activeAppId);
    if (!candidate || !isPlayAppLaunchableInEnvironment(candidate, environment)) {
      return null;
    }

    return candidate;
  }, [activeAppId, environment, playAppEntries]);

  const readyCount = useMemo(
    () => playAppEntries.filter((entry) => isPlayAppLaunchableInEnvironment(entry, environment)).length,
    [environment, playAppEntries],
  );

  useEffect(() => {
    let isDisposed = false;
    setIsLoadingPlayApps(true);

    void loadPlayAppEntriesFromServer()
      .then((entries) => {
        if (!isDisposed) {
          setPlayAppEntries(entries);
        }
      })
      .catch(() => undefined)
      .finally(() => {
        if (!isDisposed) {
          setIsLoadingPlayApps(false);
        }
      });

    return () => {
      isDisposed = true;
    };
  }, []);

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

    const mediaQuery = window.matchMedia('(max-width: 768px)');
    const handleChange = () => {
      setIsCompactViewport(mediaQuery.matches);
    };

    handleChange();
    mediaQuery.addEventListener('change', handleChange);

    return () => {
      mediaQuery.removeEventListener('change', handleChange);
    };
  }, []);

  useLayoutEffect(() => {
    if (typeof window === 'undefined' || !activeAppEntry || activeAppEntry.id === 'e-reader') {
      return undefined;
    }

    const startPath = `${location.pathname}${location.search}${location.hash}`;
    const manifestObjectUrl = createInstallManifestObjectUrl({
      startPath,
      scope: location.pathname,
      name: activeAppEntry.name,
      shortName: activeAppEntry.name,
      description: `${activeAppEntry.name} 앱을 홈 화면에서 바로 엽니다.`,
      themeColor: resolvePlayAppInstallThemeColor(activeAppEntry.id),
      backgroundColor: '#eff5ff',
    });
    const restoreManifest = swapInstallDocumentMetadata({
      manifestHref: manifestObjectUrl,
      title: activeAppEntry.name,
      themeColor: resolvePlayAppInstallThemeColor(activeAppEntry.id),
    });

    return () => {
      restoreManifest();
      if (manifestObjectUrl) {
        window.URL.revokeObjectURL(manifestObjectUrl);
      }
    };
  }, [activeAppEntry, location.hash, location.pathname, location.search]);

  const openApp = (appId: string) => {
    const currentPath = `${location.pathname}${location.search}${location.hash}`;
    setSearchParams(new URLSearchParams(buildPlayAppPath(appId, 'embedded', currentPath).split('?')[1] ?? ''));
  };

  const closeApp = () => {
    if (returnTo) {
      navigate(returnTo);
      return;
    }

    const nextSearchParams = new URLSearchParams(searchParams);
    nextSearchParams.delete('app');
    nextSearchParams.delete('launchContext');
    nextSearchParams.delete('returnTo');
    setSearchParams(nextSearchParams);
  };

  if (activeAppEntry?.id === 'photoprism') {
    return <PhotoPrismAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'baseball-ticket-bay') {
    return <BaseballTicketBayPlayAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'e-reader') {
    return <EReaderAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'photo-puzzle') {
    return <PhotoPuzzleAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'tetris') {
    return <TetrisAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'the-quest') {
    return <TheQuestAppView onBack={closeApp} launchContext={launchContext} />;
  }

  if (activeAppEntry?.id === 'template1') {
    return <Template1PlayAppView onBack={closeApp} launchContext={launchContext} />;
  }

  return (
    <section className="apps-library" data-testid="apps-library">
      <header className="apps-library__topbar">
        <div className="apps-library__title">
          <strong>앱 보관함</strong>
          <span>{playAppEntries.length}개</span>
        </div>
        <Tag bordered={false} color="gold">
          {isLoadingPlayApps ? '실행 가능 로딩중' : `실행 가능 ${readyCount}`}
        </Tag>
      </header>

      <div className={`apps-library__shelf${isCompactViewport ? ' apps-library__shelf--compact' : ''}`}>
        {playAppEntries.map((entry) => (
          <button
            key={entry.id}
            type="button"
            className={`apps-library__card ${
              entry.accentClassName
            }${isPlayAppLaunchableInEnvironment(entry, environment) ? ' apps-library__card--ready' : ''}`}
            disabled={!isPlayAppLaunchableInEnvironment(entry, environment)}
            data-testid={
              entry.id === 'e-reader'
                ? 'apps-library-open-e-reader'
                : entry.id === 'baseball-ticket-bay'
                ? 'apps-library-open-baseball-ticket-bay'
                : entry.id === 'photoprism'
                ? 'apps-library-open-photoprism'
                : entry.id === 'photo-puzzle'
                ? 'apps-library-open-photo-puzzle'
                : entry.id === 'tetris'
                  ? 'apps-library-open-tetris'
                : entry.id === 'the-quest'
                  ? 'apps-library-open-the-quest'
                  : entry.id === 'template1'
                    ? 'apps-library-open-template1'
                  : undefined
            }
            onClick={() => openApp(entry.id)}
          >
            <span className="apps-library__icon">{entry.icon}</span>
            <strong>{entry.name}</strong>
            <span className="apps-library__meta">{entry.statusLabel}</span>
          </button>
        ))}
      </div>
    </section>
  );
}
