import React, { useState, useEffect, useCallback } from 'react';
import { Box, Text } from 'folds';
import * as css from './UpdateNotification.css';

interface UpdateInfo {
  version: string;
  releaseNotes?: string;
  releaseDate?: string;
  mock?: boolean;
}

interface DownloadProgress {
  percent: number;
  transferred: number;
  total: number;
  mock?: boolean;
}

type UpdaterPhase = 'idle' | 'checking' | 'available' | 'downloading' | 'ready';

export function UpdateNotification() {
  const [phase, setPhase] = useState<UpdaterPhase>('idle');
  const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);
  const [downloadProgress, setDownloadProgress] = useState(0);
  const [isMock, setIsMock] = useState(false);
  const [hovered, setHovered] = useState(false);

  useEffect(() => {
    const electron = (window as any).electron;
    if (!electron?.updater) return undefined;

    const { updater } = electron;

    updater.isMock?.().then((result: { success?: boolean; data?: { mock?: boolean } }) => {
      if (result?.data?.mock) setIsMock(true);
    }).catch(() => {});

    updater.onUpdateAvailable((info: UpdateInfo) => {
      setUpdateInfo(info);
      if (info.mock) setIsMock(true);
      setPhase('available');
      setDownloadProgress(0);
    });

    updater.onUpdateDownloadProgress((progress: DownloadProgress) => {
      setPhase('downloading');
      setDownloadProgress(Math.min(100, Math.round(progress.percent)));
    });

    updater.onUpdateDownloaded((info: UpdateInfo) => {
      setUpdateInfo(info);
      setPhase('ready');
      setDownloadProgress(100);
    });

    const onNotAvailable = () => {
      setPhase('idle');
      setUpdateInfo(null);
      setDownloadProgress(0);
    };
    // Optional channel — ignore if preload doesn't expose a dedicated listener
    if (electron.updater.onUpdateNotAvailable) {
      electron.updater.onUpdateNotAvailable(onNotAvailable);
    }

    return undefined;
  }, []);

  const handleCheck = useCallback(async () => {
    setPhase('checking');
    try {
      const result = await (window as any).electron.updater.checkForUpdates();
      if (!result?.success) {
        setPhase('idle');
      }
      // available event will advance phase; if nothing comes, fall back
      window.setTimeout(() => {
        setPhase((current) => (current === 'checking' ? 'idle' : current));
      }, 4000);
    } catch {
      setPhase('idle');
    }
  }, []);

  const handleDownload = useCallback(async () => {
    setPhase('downloading');
    setDownloadProgress(0);
    try {
      await (window as any).electron.updater.downloadUpdate();
    } catch {
      setPhase('available');
    }
  }, []);

  const handleInstall = useCallback(async () => {
    try {
      await (window as any).electron.updater.installUpdate();
      if (isMock) {
        setPhase('idle');
        setUpdateInfo(null);
        setDownloadProgress(0);
      }
    } catch {
      // keep ready state
    }
  }, [isMock]);

  const handleDismiss = useCallback(() => {
    setPhase('idle');
    setUpdateInfo(null);
    setDownloadProgress(0);
  }, []);

  if (typeof window === 'undefined' || !(window as any).electron?.updater) {
    return null;
  }

  if (phase === 'idle') {
    return (
      <div
        className={css.IdleSlot}
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
      >
        <button
          type="button"
          className={css.GhostCheck}
          data-visible={hovered || isMock ? 'true' : undefined}
          onClick={handleCheck}
          title={isMock ? 'Check for updates (mock)' : 'Check for updates'}
          aria-label="Check for updates"
        >
          <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden>
            <path
              d="M8 2V10M8 10L5 7M8 10L11 7"
              stroke="currentColor"
              strokeWidth="1.5"
              strokeLinecap="round"
              strokeLinejoin="round"
            />
            <path d="M3 14H13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
          </svg>
        </button>
      </div>
    );
  }

  if (phase === 'checking') {
    return (
      <div className={css.Bar} title="Checking for updates…">
        <div className={css.BarTrack}>
          <div className={css.BarIndeterminate} />
        </div>
        <Text className={css.BarLabel} size="L400">
          Checking…
        </Text>
      </div>
    );
  }

  if (phase === 'downloading') {
    return (
      <div
        className={css.Bar}
        title={`Downloading update${updateInfo ? ` ${updateInfo.version}` : ''}… ${downloadProgress}%`}
      >
        <div className={css.BarTrack}>
          <div className={css.BarFill} style={{ width: `${downloadProgress}%` }} />
        </div>
        <Text className={css.BarLabel} size="L400">
          {downloadProgress}%
        </Text>
      </div>
    );
  }

  if (phase === 'ready') {
    return (
      <Box className={css.Chip} alignItems="Center" gap="100">
        <Text className={css.ChipText} size="L400" truncate>
          {isMock ? 'Mock ready' : 'Update ready'}
          {updateInfo ? ` · ${updateInfo.version}` : ''}
        </Text>
        <button type="button" className={css.ChipAction} onClick={handleInstall}>
          Restart
        </button>
      </Box>
    );
  }

  // available
  return (
    <Box className={css.Chip} alignItems="Center" gap="100">
      <Text className={css.ChipText} size="L400" truncate>
        {isMock ? 'Mock update' : 'Update'}
        {updateInfo ? ` ${updateInfo.version}` : ''}
      </Text>
      <button type="button" className={css.ChipAction} onClick={handleDownload}>
        Download
      </button>
      <button
        type="button"
        className={css.ChipDismiss}
        onClick={handleDismiss}
        aria-label="Dismiss update"
        title="Dismiss"
      >
        ×
      </button>
    </Box>
  );
}
