import React, { useEffect, useState } from 'react';
import {
  runStartupAutoUpdate,
  type DesktopUpdatePhase,
  type DesktopUpdateProgress,
} from './bridge/updater';
import '@frontend/App.css';

const PHASE_LABEL: Record<DesktopUpdatePhase, string> = {
  checking: '업데이트 확인 중',
  uptodate: '최신 버전',
  available: '새 버전 발견',
  downloading: '다운로드 중',
  installing: '설치 중',
  relaunching: '재시작 중',
  error: '업데이트 실패',
};

function formatBytes(n?: number): string {
  if (n == null || !Number.isFinite(n) || n <= 0) return '';
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
  return `${(n / (1024 * 1024)).toFixed(1)} MB`;
}

function StartupUpdateSplash({ progress }: { progress: DesktopUpdateProgress | null }) {
  const phase = progress?.phase ?? 'checking';
  const isActive = phase === 'checking' || phase === 'downloading' || phase === 'installing' || phase === 'relaunching';
  const showBar = phase === 'available' || phase === 'downloading' || phase === 'installing';
  const barPct = phase === 'installing' ? 100 : progress?.downloadPercent;

  const panelClass = phase === 'error'
    ? 'desktop-update-progress--failed'
    : isActive
      ? 'desktop-update-progress--active'
      : '';

  return (
    <div className="desktop-startup-update">
      <div className="desktop-startup-update-card">
        <h1 className="desktop-startup-update-title">GoldenChart</h1>
        <p className="desktop-startup-update-sub">
          {progress?.currentVersion ? `현재 v${progress.currentVersion}` : '시작 중…'}
          {progress?.newVersion && progress.newVersion !== progress.currentVersion && (
            <> → v{progress.newVersion}</>
          )}
        </p>

        <div className={`desktop-update-progress ${panelClass}`.trim()}>
          <div className="desktop-update-progress-head">
            <span className="desktop-update-progress-title">
              {isActive && <span className="desktop-update-spinner" aria-hidden />}
              {PHASE_LABEL[phase]}
            </span>
            {phase === 'downloading' && progress?.downloadPercent != null && (
              <span className="desktop-update-pct">{progress.downloadPercent}%</span>
            )}
          </div>

          {showBar && (
            <div
              className="desktop-update-bar"
              role="progressbar"
              aria-valuemin={0}
              aria-valuemax={100}
              aria-valuenow={barPct ?? undefined}
            >
              {barPct != null ? (
                <div
                  className="desktop-update-bar-fill desktop-update-bar-fill--determinate"
                  style={{ width: `${barPct}%` }}
                />
              ) : (
                <div className="desktop-update-bar-fill desktop-update-bar-fill--indeterminate" />
              )}
            </div>
          )}

          <ul className="desktop-update-steps">
            <li className={`desktop-update-step${phase === 'checking' ? ' active' : phase !== 'error' ? ' done' : ''}`}>
              <span className="desktop-update-step-dot" aria-hidden />
              서버에서 버전 확인
            </li>
            <li className={`desktop-update-step${
              phase === 'available' || phase === 'downloading' ? ' active'
                : ['installing', 'relaunching', 'uptodate'].includes(phase) ? ' done' : ''
            }`}>
              <span className="desktop-update-step-dot" aria-hidden />
              업데이트 다운로드
              {progress?.downloadedBytes && progress.totalBytes ? (
                <span className="desktop-update-bytes">
                  {formatBytes(progress.downloadedBytes)} / {formatBytes(progress.totalBytes)}
                </span>
              ) : null}
            </li>
            <li className={`desktop-update-step${
              phase === 'installing' ? ' active' : phase === 'relaunching' || phase === 'uptodate' ? ' done' : ''
            }`}>
              <span className="desktop-update-step-dot" aria-hidden />
              설치 및 재시작
            </li>
          </ul>

          {progress?.message && (
            <p className={`desktop-update-message${phase === 'error' ? ' desktop-update-message--error' : ''}`}>
              {progress.message}
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

/** StrictMode 이중 실행 방지 — 시작 업데이트는 한 번만 */
let startupUpdateTask: ReturnType<typeof runStartupAutoUpdate> | null = null;
const startupProgressListeners = new Set<(p: DesktopUpdateProgress) => void>();

function emitStartupProgress(p: DesktopUpdateProgress) {
  for (const listener of startupProgressListeners) listener(p);
}

function getStartupUpdateTask() {
  if (!startupUpdateTask) {
    startupUpdateTask = runStartupAutoUpdate(emitStartupProgress);
  }
  return startupUpdateTask;
}

/** 시작 시 자동 업데이트 후 children(메인 앱) 렌더 */
export function StartupUpdateGate({ children }: { children: React.ReactNode }) {
  const [ready, setReady] = useState(false);
  const [progress, setProgress] = useState<DesktopUpdateProgress | null>({
    phase: 'checking',
    message: '서버에서 새 버전을 확인하는 중…',
  });

  useEffect(() => {
    const listener = (p: DesktopUpdateProgress) => setProgress(p);
    startupProgressListeners.add(listener);

    void getStartupUpdateTask().then(({ shouldContinue, result }) => {
      if (!shouldContinue) return;
      if (result.phase === 'error') {
        console.warn('[startup-update]', result.message);
      }
      setReady(true);
    });

    return () => {
      startupProgressListeners.delete(listener);
    };
  }, []);

  if (!ready) {
    return <StartupUpdateSplash progress={progress} />;
  }

  return <>{children}</>;
}
