import { useEffect, useState } from 'react'
import type { YtdlpVersionResult, YtdlpUpdateResult, FfmpegVersionResult } from '@shared/ipc'
import { useSettings } from '../../store/settings'
import { logError } from '../../reportError'

export interface AboutCardController {
  checking: boolean
  version: YtdlpVersionResult | null
  ffmpeg: FfmpegVersionResult | null
  updating: boolean
  updateResult: YtdlpUpdateResult | null
  checkVersion: () => Promise<void>
  runUpdate: () => Promise<void>
  refreshFfmpeg: () => void
}

/**
 * View-model for the About card (L93/CC13): owns the yt-dlp/ffmpeg version state
 * and the update orchestration so the card stays presentational — no `window.api`
 * in the component (the `useDownloadBar` pattern).
 */
export function useAboutCard(): AboutCardController {
  const ytdlpChannel = useSettings((s) => s.ytdlpChannel)

  // `checking` starts true: the mount effect immediately loads the version, and
  // the card shows a skeleton line for that boot load instead of a blank (L109).
  const [checking, setChecking] = useState(true)
  const [version, setVersion] = useState<YtdlpVersionResult | null>(null)
  const [ffmpeg, setFfmpeg] = useState<FfmpegVersionResult | null>(null)
  const [updating, setUpdating] = useState(false)
  const [updateResult, setUpdateResult] = useState<YtdlpUpdateResult | null>(null)

  useEffect(() => {
    // Show the current yt-dlp version without a manual click, and reflect a
    // background auto-update (which may run on launch) live in this panel.
    window.api
      .getYtdlpVersion()
      .then(setVersion)
      .catch(logError('getYtdlpVersion'))
      .finally(() => setChecking(false))
    // ffmpeg/ffprobe are display-only (fetched on first run, not auto-updated); load them once.
    // On a bridge failure, settle to "not found" rather than a permanent skeleton.
    window.api
      .getFfmpegVersions()
      .then(setFfmpeg)
      .catch((e) => {
        logError('getFfmpegVersions')(e)
        setFfmpeg({ ffmpeg: null, ffprobe: null })
      })
    return window.api.onYtdlpAutoUpdateStatus((s) => {
      if (s.phase === 'checking') {
        setChecking(true)
        return
      }
      setChecking(false)
      if (s.version) setVersion({ ok: true, version: s.version })
      if (s.checkedAt) useSettings.setState({ ytdlpLastUpdateCheck: s.checkedAt })
      if (s.phase === 'updated') {
        setUpdateResult({ ok: true, output: `Updated to yt-dlp ${s.version ?? ''}`.trim() })
      } else if (s.phase === 'error' && s.error) {
        setUpdateResult({ ok: false, error: s.error })
      }
    })
  }, [])

  async function checkVersion(): Promise<void> {
    setChecking(true)
    setVersion(null)
    try {
      setVersion(await window.api.getYtdlpVersion())
    } catch (e) {
      setVersion({ ok: false, error: e instanceof Error ? e.message : String(e) })
    } finally {
      setChecking(false)
    }
  }

  async function runUpdate(): Promise<void> {
    setUpdating(true)
    setUpdateResult(null)
    try {
      const result = await window.api.updateYtdlp(ytdlpChannel)
      setUpdateResult(result)
      if (result.ok) setVersion(null) // stale -- prompt a re-check rather than show a wrong version
    } catch (e) {
      setUpdateResult({ ok: false, error: e instanceof Error ? e.message : String(e) })
    } finally {
      setUpdating(false)
    }
  }

  function refreshFfmpeg(): void {
    window.api.getFfmpegVersions().then(setFfmpeg).catch(logError('getFfmpegVersions'))
  }

  return {
    checking,
    version,
    ffmpeg,
    updating,
    updateResult,
    checkVersion,
    runUpdate,
    refreshFfmpeg
  }
}
