// =====================================================================
//  Bandeau « une mise à jour est disponible ».
//
//  Discret : une bande fine en haut de l'application, jamais une modale
//  qui interrompt le travail. On peut reporter — la proposition revient
//  au prochain lancement.
// =====================================================================

import { useCallback, useEffect, useState } from 'react'
import { AnimatePresence, motion } from 'framer-motion'
import { Download, RefreshCw, Sparkles, X } from 'lucide-react'
import { AvailableUpdate, checkForUpdate } from '../lib/updater'
import { useFeedback } from '../lib/feedback'
import { Button, IconButton } from './ui'

/** Nouvelle vérification toutes les 2 heures pour les sessions qui durent. */
const RECHECK_MS = 2 * 60 * 60 * 1000

export default function UpdateBanner(): JSX.Element | null {
  const { toast } = useFeedback()
  const [update, setUpdate] = useState<AvailableUpdate | null>(null)
  const [dismissed, setDismissed] = useState(false)
  const [installing, setInstalling] = useState(false)
  const [progress, setProgress] = useState<number | null>(null)

  const look = useCallback(async () => {
    const found = await checkForUpdate()
    if (found) setUpdate(found)
  }, [])

  useEffect(() => {
    // Au démarrage, mais sans retarder l'affichage de l'application.
    const first = setTimeout(look, 4000)
    const timer = setInterval(look, RECHECK_MS)
    return () => {
      clearTimeout(first)
      clearInterval(timer)
    }
  }, [look])

  if (!update || dismissed) return null

  const install = async (): Promise<void> => {
    setInstalling(true)
    setProgress(0)
    try {
      // Au succès l'application redémarre : rien à faire de plus ici.
      await update.install((pct) => setProgress(pct))
    } catch (e) {
      setInstalling(false)
      setProgress(null)
      toast(
        `La mise à jour a échoué : ${(e as Error).message}. Réessaie plus tard ou préviens l'administrateur.`,
        'error'
      )
    }
  }

  return (
    <AnimatePresence>
      <motion.div
        initial={{ height: 0, opacity: 0 }}
        animate={{ height: 'auto', opacity: 1 }}
        exit={{ height: 0, opacity: 0 }}
        className="shrink-0 overflow-hidden border-b border-accent/25 bg-accent/10"
      >
        <div className="flex items-center gap-3 px-4 py-2">
          <Sparkles size={15} className="shrink-0 text-accent" />

          <span className="min-w-0 flex-1 text-xs text-ink">
            <span className="font-medium">Version {update.version} disponible.</span>{' '}
            {installing ? (
              <span className="text-muted">
                {progress === null || progress === 0
                  ? 'Téléchargement…'
                  : progress < 100
                    ? `Téléchargement ${progress} %…`
                    : 'Installation, l’application va redémarrer…'}
              </span>
            ) : (
              <span className="text-muted">
                {update.notes?.split('\n')[0] || "L'application se relancera toute seule."}
              </span>
            )}
          </span>

          {installing ? (
            <div className="h-1 w-32 shrink-0 overflow-hidden rounded-full bg-accent/20">
              <div
                className={`h-full rounded-full bg-accent transition-[width] duration-300 ${
                  progress === null ? 'w-1/3 animate-pulse' : ''
                }`}
                style={progress === null ? undefined : { width: `${progress}%` }}
              />
            </div>
          ) : (
            <>
              <Button size="sm" variant="primary" icon={<Download size={13} />} onClick={install}>
                Installer et redémarrer
              </Button>
              <IconButton
                size="sm"
                label="Plus tard"
                icon={<X size={15} />}
                onClick={() => setDismissed(true)}
              />
            </>
          )}
        </div>
      </motion.div>
    </AnimatePresence>
  )
}

/** Ligne « Version X · Rechercher une mise à jour », pour l'écran d'aide. */
export function UpdateCheckRow({ version }: { version: string | null }): JSX.Element {
  const { toast } = useFeedback()
  const [busy, setBusy] = useState(false)

  const look = async (): Promise<void> => {
    setBusy(true)
    const found = await checkForUpdate()
    setBusy(false)
    toast(
      found
        ? `Version ${found.version} disponible — le bandeau apparaît en haut de l'écran.`
        : 'Tu es déjà à jour.',
      found ? 'info' : 'success'
    )
  }

  return (
    <div className="flex items-center justify-between gap-4 border-t border-border pt-3 text-sm">
      <span className="text-muted">
        Version installée <span className="font-medium text-ink">{version ?? '—'}</span>
      </span>
      <Button size="sm" icon={<RefreshCw size={13} />} loading={busy} onClick={look}>
        Rechercher une mise à jour
      </Button>
    </div>
  )
}
