import {
  Field,
  Switch,
  Button,
  Card,
  Subtitle2,
  Caption1,
  Text,
  Spinner,
  ProgressBar,
  Skeleton,
  SkeletonItem
} from '@fluentui/react-components'
import {
  InfoRegular,
  ArrowSyncRegular,
  ArrowDownloadRegular,
  DismissRegular,
  FolderRegular
} from '@fluentui/react-icons'
import { type YtdlpUpdateChannel } from '@shared/ipc'
import { useSettings } from '../../store/settings'
import { useSetup } from '../../store/setup'
import { Select } from '../../components/Select'
import { useErrorTextStyles } from '../../components/ui/errorText'
import { useSettingsStyles } from './settingsStyles'
import { useAboutCard } from './useAboutCard'

const UPDATE_CHANNEL_OPTIONS = [
  { value: 'stable', label: 'Stable' },
  { value: 'nightly', label: 'Nightly' }
]

export function AboutCard(): React.JSX.Element {
  const styles = useSettingsStyles()
  const errText = useErrorTextStyles()
  const autoUpdateYtdlp = useSettings((s) => s.autoUpdateYtdlp)
  const ytdlpChannel = useSettings((s) => s.ytdlpChannel)
  const ytdlpLastUpdateCheck = useSettings((s) => s.ytdlpLastUpdateCheck)
  const update = useSettings((s) => s.update)

  // View-model hook owns the version/update state + IPC (L93/CC13).
  const {
    checking,
    version,
    ffmpeg,
    updating,
    updateResult,
    checkVersion,
    runUpdate,
    refreshFfmpeg
  } = useAboutCard()

  // ffmpeg is fetched on first run (not bundled); the setup store owns its download/locate
  // orchestration + progress. Re-read the displayed versions once an action settles.
  const ffmpegReady = useSetup((s) => s.ffmpegReady)
  const setupBusy = useSetup((s) => s.busy)
  const setupPhase = useSetup((s) => s.phase)
  const setupFraction = useSetup((s) => s.fraction)
  const setupError = useSetup((s) => s.error)
  const downloadFfmpeg = useSetup((s) => s.download)
  const cancelFfmpeg = useSetup((s) => s.cancel)
  const locateFfmpeg = useSetup((s) => s.locate)
  async function getFfmpeg(): Promise<void> {
    await downloadFfmpeg()
    refreshFfmpeg()
  }
  async function locate(): Promise<void> {
    await locateFfmpeg()
    refreshFfmpeg()
  }

  return (
    <Card className={styles.card}>
      <div className={styles.sectionHeader}>
        <InfoRegular className={styles.sectionIcon} />
        <Subtitle2 as="h3">About</Subtitle2>
      </div>
      <Caption1 className={styles.hint}>
        AeroFetch is a generic frontend for yt-dlp. It manages its own copy of yt-dlp (keeping it up
        to date automatically) and downloads ffmpeg on first run.
      </Caption1>
      <div className={styles.folderRow}>
        {/* Re-show the first-run welcome/tips screen on demand (UX22). */}
        <Button size="small" onClick={() => update({ hasCompletedOnboarding: false })}>
          Show welcome tips again
        </Button>
      </div>

      <Field
        label="Keep yt-dlp updated automatically"
        hint="Checks once a day on launch and updates the downloader in the background, so site changes don't start breaking your downloads."
      >
        <Switch
          checked={autoUpdateYtdlp}
          onChange={(_, d) => update({ autoUpdateYtdlp: d.checked })}
        />
      </Field>

      {/* Boot loading state (L109/UX26): the versions load automatically on mount,
          so show skeleton lines instead of a blank until they arrive. */}
      {!version && checking && (
        <Skeleton aria-label="Loading yt-dlp version">
          <SkeletonItem size={16} style={{ maxWidth: '180px' }} />
        </Skeleton>
      )}
      {version?.ok && <Text className={styles.mono}>yt-dlp {version.version}</Text>}
      {version && !version.ok && <Caption1 className={errText.errorPre}>{version.error}</Caption1>}
      {!ffmpeg && (
        <Skeleton aria-label="Loading ffmpeg versions">
          <SkeletonItem size={16} style={{ maxWidth: '220px' }} />
        </Skeleton>
      )}
      {ffmpeg && (
        <div className={styles.folderRow}>
          <div>
            <Text className={styles.monoBlock}>ffmpeg {ffmpeg.ffmpeg ?? 'not found'}</Text>
            <Text className={styles.monoBlock}>ffprobe {ffmpeg.ffprobe ?? 'not found'}</Text>
          </div>
          <Button
            appearance="subtle"
            icon={<ArrowSyncRegular />}
            onClick={refreshFfmpeg}
            aria-label="Re-check ffmpeg versions"
          />
        </div>
      )}
      {ffmpeg &&
        (setupBusy ? (
          <>
            <ProgressBar
              value={setupPhase === 'extracting' ? undefined : setupFraction}
              aria-label="ffmpeg setup progress"
            />
            <div className={styles.folderRow}>
              <Caption1 className={styles.hint}>
                {setupPhase === 'extracting' ? 'Unpacking…' : 'Downloading ffmpeg…'}
              </Caption1>
              {/* Only the download is cancelable — unpacking runs to completion. */}
              {setupPhase === 'downloading' && (
                <Button
                  size="small"
                  appearance="subtle"
                  icon={<DismissRegular />}
                  onClick={cancelFfmpeg}
                >
                  Cancel
                </Button>
              )}
            </div>
          </>
        ) : (
          <div className={styles.folderRow}>
            <Button icon={<ArrowDownloadRegular />} onClick={() => void getFfmpeg()}>
              {ffmpegReady === true ? 'Repair ffmpeg' : 'Download ffmpeg'}
            </Button>
            <Button icon={<FolderRegular />} onClick={() => void locate()}>
              Locate existing…
            </Button>
          </div>
        ))}
      {setupError && <Caption1 className={errText.errorPre}>{setupError}</Caption1>}
      {ytdlpLastUpdateCheck > 0 && (
        <Caption1 className={styles.hint}>
          Last checked for updates {new Date(ytdlpLastUpdateCheck).toLocaleString()}.
        </Caption1>
      )}
      <div className={styles.folderRow}>
        <Button
          icon={checking ? <Spinner size="tiny" /> : <ArrowSyncRegular />}
          onClick={checkVersion}
          disabled={checking}
        >
          Check yt-dlp version
        </Button>
      </div>

      <Field
        label="Update channel"
        hint="Nightly tracks yt-dlp's daily build; stable is the tagged release. Nightly follows YouTube changes fastest."
      >
        <Select
          value={ytdlpChannel}
          options={UPDATE_CHANNEL_OPTIONS}
          onChange={(v) => update({ ytdlpChannel: v as YtdlpUpdateChannel })}
        />
      </Field>
      <div className={styles.folderRow}>
        <Button
          icon={updating ? <Spinner size="tiny" /> : <ArrowSyncRegular />}
          onClick={runUpdate}
          disabled={updating}
        >
          {updating ? 'Updating…' : 'Update yt-dlp'}
        </Button>
      </div>
      {updateResult?.ok && (
        <Text className={styles.monoPre}>
          {updateResult.output || 'yt-dlp is already up to date.'}
        </Text>
      )}
      {updateResult && !updateResult.ok && (
        <Caption1 className={errText.errorPre}>{updateResult.error}</Caption1>
      )}
    </Card>
  )
}
