import {
  AppstoreOutlined,
  AppstoreAddOutlined,
  BellOutlined,
  BookOutlined,
  FileImageOutlined,
  FireOutlined,
  FundProjectionScreenOutlined,
  PictureOutlined,
  RocketOutlined,
  SoundOutlined,
  StarOutlined,
  ThunderboltOutlined,
} from '@ant-design/icons';
import type { ReactNode } from 'react';

export type PlayAppEnvironment = 'preview' | 'test' | 'prod';

type PlayAppServerRow = {
  id: string;
  name: string;
  accentClassName: string;
  statusLabel: string;
  isReady: boolean;
  iconName: string;
  usagePriority?: number;
  supportedEnvironments?: PlayAppEnvironment[];
  searchKeywords?: string[];
  searchDescription?: string;
};

export type PlayAppEntry = {
  id: string;
  name: string;
  accentClassName: string;
  statusLabel: string;
  isReady: boolean;
  icon: ReactNode;
  usagePriority?: number;
  supportedEnvironments?: PlayAppEnvironment[];
  searchKeywords?: string[];
  searchDescription?: string;
};

const PLAY_APP_ICON_REGISTRY: Record<string, ReactNode> = {
  AppstoreOutlined: <AppstoreOutlined />,
  AppstoreAddOutlined: <AppstoreAddOutlined />,
  BellOutlined: <BellOutlined />,
  BookOutlined: <BookOutlined />,
  FireOutlined: <FireOutlined />,
  FundProjectionScreenOutlined: <FundProjectionScreenOutlined />,
  FileImageOutlined: <FileImageOutlined />,
  PictureOutlined: <PictureOutlined />,
  RocketOutlined: <RocketOutlined />,
  SoundOutlined: <SoundOutlined />,
  StarOutlined: <StarOutlined />,
  ThunderboltOutlined: <ThunderboltOutlined />,
};

const PLAY_APP_API_PATH = '/api/play-apps';
const FALLBACK_ICON = <AppstoreOutlined />;

const FALLBACK_ENTRIES: PlayAppEntry[] = [
  {
    id: 'baseball-ticket-bay',
    name: '야구-티켓베이',
    accentClassName: 'apps-library__card--baseball-ticket-bay',
    statusLabel: '알림',
    isReady: true,
    icon: <BellOutlined />,
    usagePriority: 100,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['야구', '티켓베이', 'ticketbay', '야구 티켓', '웹푸시', '알림'],
    searchDescription: '팀, 구역, 통로, 가격 조건으로 야구 티켓 알림 조건을 저장하고 테스트 푸시를 보냅니다.',
  },
  {
    id: 'e-reader',
    name: 'E-Reader',
    accentClassName: 'apps-library__card--reader',
    statusLabel: '읽기',
    isReady: true,
    icon: <BookOutlined />,
    usagePriority: 80,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['e-reader', 'reader', 'ebook', 'article', 'web article', '기사', '전자책', '리더'],
    searchDescription: 'Apps 보관함에서 인터넷 기사와 웹 콘텐츠를 전자책처럼 넘겨 읽습니다.',
  },
  {
    id: 'photoprism',
    name: 'PhotoPrism',
    accentClassName: 'apps-library__card--photoprism',
    statusLabel: '연결',
    isReady: true,
    icon: <FileImageOutlined />,
    usagePriority: 70,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['photoprism', 'photo', 'album', 'gallery', '사진 앨범'],
    searchDescription: 'Apps 보관함에서 PhotoPrism 앨범과 사진을 단독 앱 형태로 엽니다.',
  },
  {
    id: 'photo-puzzle',
    name: '사진 퍼즐',
    accentClassName: 'apps-library__card--puzzle',
    statusLabel: '실행',
    isReady: true,
    icon: <PictureOutlined />,
    usagePriority: 60,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['photo puzzle', '퍼즐', '사진', '슬라이드 퍼즐'],
    searchDescription: 'Apps 보관함에서 사진 퍼즐 게임을 바로 실행합니다.',
  },
  {
    id: 'the-quest',
    name: 'The Quest',
    accentClassName: 'apps-library__card--the-quest',
    statusLabel: '신규',
    isReady: true,
    icon: <ThunderboltOutlined />,
    usagePriority: 50,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['the quest', 'rpg', 'mobile rpg', 'phaser', 'quest', 'rpg game', '모바일 rpg'],
    searchDescription: 'Apps 보관함에서 한국형 모바일 RPG 데모 The Quest를 실행합니다.',
  },
  {
    id: 'template1',
    name: 'Template1',
    accentClassName: 'apps-library__card--template1',
    statusLabel: '템플릿',
    isReady: true,
    icon: <AppstoreAddOutlined />,
    usagePriority: 45,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['template1', 'template', '앱 템플릿', '레이아웃', '기본 UI', 'layout'],
    searchDescription: '다른 앱 개발 시 공통 레이아웃을 빠르게 적용하기 위한 템플릿 화면입니다.',
  },
  {
    id: 'tetris',
    name: 'Tetris',
    accentClassName: 'apps-library__card--tetris',
    statusLabel: '실행',
    isReady: true,
    icon: <FundProjectionScreenOutlined />,
    usagePriority: 40,
    supportedEnvironments: ['preview', 'test'],
    searchKeywords: ['테트리스', 'block', 'arcade', '블록 게임'],
    searchDescription: 'Apps 보관함에서 테트리스 게임을 바로 실행합니다.',
  },
  { id: 'beat-lab', name: 'Beat Lab', accentClassName: 'apps-library__card--beat', statusLabel: '준비', isReady: false, icon: <SoundOutlined /> },
  { id: 'sticker-booth', name: 'Sticker Booth', accentClassName: 'apps-library__card--sticker', statusLabel: '준비', isReady: false, icon: <StarOutlined /> },
  { id: 'launch-note', name: 'Launch Note', accentClassName: 'apps-library__card--launch', statusLabel: '예정', isReady: false, icon: <RocketOutlined /> },
  { id: 'arcade-pack', name: 'Arcade Pack', accentClassName: 'apps-library__card--arcade', statusLabel: '예정', isReady: false, icon: <FireOutlined /> },
  { id: 'app-vault', name: 'App Vault', accentClassName: 'apps-library__card--vault', statusLabel: '테마', isReady: false, icon: <AppstoreOutlined /> },
];

export const APP_LIBRARY_ENTRIES = FALLBACK_ENTRIES;

let playAppCache = FALLBACK_ENTRIES;
let loadingPromise: Promise<PlayAppEntry[]> | null = null;

function isObjectValue(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null;
}

function parseSearchKeywords(value: unknown) {
  if (!Array.isArray(value)) {
    return [];
  }

  return value
    .map((item) => (typeof item === 'string' ? item.trim() : ''))
    .filter((item) => item.length > 0);
}

function isPlayEnvironment(value: unknown): value is PlayAppEnvironment {
  return value === 'preview' || value === 'test' || value === 'prod';
}

function normalizePlayAppServerPayload(payload: unknown): PlayAppServerRow[] {
  if (!isObjectValue(payload) || !Array.isArray(payload.items)) {
    return [];
  }

  return payload.items
    .map((raw) => {
      if (!isObjectValue(raw)) {
        return null;
      }

      const id = typeof raw.id === 'string' ? raw.id.trim() : '';
      const name = typeof raw.name === 'string' ? raw.name.trim() : '';
      const accentClassName = typeof raw.accentClassName === 'string' ? raw.accentClassName.trim() : '';
      const statusLabel = typeof raw.statusLabel === 'string' ? raw.statusLabel.trim() : '';
      const iconName = typeof raw.iconName === 'string' ? raw.iconName.trim() : '';

      if (!id || !name || !accentClassName) {
        return null;
      }

      const rawSupported = Array.isArray(raw.supportedEnvironments) ? raw.supportedEnvironments : [];
      const supportedEnvironments = rawSupported.filter(isPlayEnvironment);

      return {
        id,
        name,
        accentClassName,
        statusLabel: statusLabel || '준비',
        isReady: raw.isReady === true,
        iconName,
        usagePriority: typeof raw.usagePriority === 'number' ? raw.usagePriority : undefined,
        supportedEnvironments,
        searchKeywords: parseSearchKeywords(raw.searchKeywords),
        searchDescription: typeof raw.searchDescription === 'string' ? raw.searchDescription.trim() : '',
      } satisfies PlayAppServerRow;
    })
    .filter((item): item is PlayAppServerRow => item !== null);
}

function sortPlayAppEntriesByPriority(entries: PlayAppEntry[]) {
  return entries.slice().sort((lhs, rhs) => {
    const lhsPriority = lhs.usagePriority ?? 0;
    const rhsPriority = rhs.usagePriority ?? 0;

    if (rhsPriority !== lhsPriority) {
      return rhsPriority - lhsPriority;
    }

    return lhs.id.localeCompare(rhs.id);
  });
}

function normalizeSupportedEnvironments(rawEnvironments: PlayAppEnvironment[] | undefined) {
  if (!rawEnvironments || rawEnvironments.length === 0) {
    return ['preview'];
  }

  return rawEnvironments;
}

function getEntryWithIcon(entry: PlayAppServerRow): PlayAppEntry {
  return {
    id: entry.id,
    name: entry.name,
    accentClassName: entry.accentClassName,
    statusLabel: entry.statusLabel,
    isReady: entry.isReady,
    icon: PLAY_APP_ICON_REGISTRY[entry.iconName] ?? FALLBACK_ICON,
    usagePriority: entry.usagePriority,
    supportedEnvironments: normalizeSupportedEnvironments(entry.supportedEnvironments),
    searchKeywords: entry.searchKeywords,
    searchDescription: entry.searchDescription,
  };
}

export function getCurrentPlayAppEnvironment(): PlayAppEnvironment {
  if (typeof window === 'undefined') {
    return 'prod';
  }

  const hostname = window.location.hostname;
  const isLocalHost =
    hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '0.0.0.0';

  if (isLocalHost) {
    return 'test';
  }

  if (hostname.includes('preview')) {
    return 'preview';
  }

  return 'prod';
}

export function getSupportedPlayAppEnvironments(entry: PlayAppEntry): PlayAppEnvironment[] {
  if (entry.supportedEnvironments && entry.supportedEnvironments.length > 0) {
    return entry.supportedEnvironments;
  }

  return ['preview'];
}

export function isPlayAppSupportedInEnvironment(entry: PlayAppEntry, environment: PlayAppEnvironment) {
  return getSupportedPlayAppEnvironments(entry).includes(environment);
}

export function isPlayAppLaunchableInEnvironment(
  entry: PlayAppEntry,
  environment: PlayAppEnvironment = getCurrentPlayAppEnvironment(),
) {
  if (!isPlayAppSupportedInEnvironment(entry, environment)) {
    return false;
  }

  if (environment === 'preview') {
    return true;
  }

  return entry.isReady;
}

export function getPlayAppEntries() {
  return playAppCache;
}

export function getReadyPlayAppEntries() {
  const environment = getCurrentPlayAppEnvironment();
  return playAppCache.filter((entry) => isPlayAppLaunchableInEnvironment(entry, environment));
}

export function findReadyPlayAppEntryById(appId: string | null | undefined) {
  if (!appId) {
    return null;
  }

  const entry = playAppCache.find((candidate) => candidate.id === appId);
  if (!entry) {
    return null;
  }

  return isPlayAppLaunchableInEnvironment(entry) ? entry : null;
}

export function loadPlayAppEntriesFromServer() {
  if (typeof window === 'undefined') {
    return Promise.resolve(playAppCache);
  }

  if (!loadingPromise) {
    loadingPromise = fetch(PLAY_APP_API_PATH)
      .then(async (response) => {
        if (!response.ok) {
          throw new Error(`앱 목록 조회 실패: ${response.status}`);
        }

        const payload = await response.json();
        const normalizedRows = normalizePlayAppServerPayload(payload).map(getEntryWithIcon);
        playAppCache = sortPlayAppEntriesByPriority(normalizedRows.length ? normalizedRows : FALLBACK_ENTRIES);

        return playAppCache;
      })
      .catch(() => {
        playAppCache = FALLBACK_ENTRIES;
        return playAppCache;
      })
      .finally(() => {
        loadingPromise = null;
      });
  }

  return loadingPromise;
}
