import {
  Card,
  Title2,
  Body1,
  Caption1,
  Field,
  Button,
  Spinner,
  ProgressBar,
  makeStyles,
  mergeClasses,
  tokens,
  shorthands
} from '@fluentui/react-components'
import {
  ArrowDownloadFilled,
  ArrowDownloadRegular,
  DismissRegular,
  CheckmarkCircleFilled,
  ClipboardPasteRegular,
  HistoryRegular,
  OptionsRegular,
  RocketRegular,
  FolderRegular,
  MusicNote2Regular,
  VideoClipRegular,
  KeyboardRegular
} from '@fluentui/react-icons'
import { useSettings } from '../store/settings'
import { useSetup } from '../store/setup'
import { useErrorTextStyles } from '../components/ui/errorText'
import { SPACE, ICON } from '../components/ui/tokens'

const useStyles = makeStyles({
  root: {
    height: '100%',
    width: '100%',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    overflowY: 'auto',
    padding: SPACE.page
  },
  card: {
    display: 'flex',
    flexDirection: 'column',
    gap: SPACE.roomy,
    // The welcome hero card (UI3 hero tier).
    padding: SPACE.hero,
    maxWidth: '460px',
    width: '100%',
    ...shorthands.borderRadius(tokens.borderRadiusXLarge)
  },
  brandRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '14px'
  },
  mark: {
    width: '48px',
    height: '48px',
    flexShrink: 0,
    ...shorthands.borderRadius(tokens.borderRadiusLarge),
    backgroundColor: tokens.colorBrandBackground,
    color: tokens.colorNeutralForegroundOnBrand,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    // Brand tile glyph, snapped to the nearest ICON tier (UI11 — no literal px).
    fontSize: `${ICON.section}px`
  },
  folderNote: {
    color: tokens.colorNeutralForeground3,
    marginBottom: SPACE.tight
  },
  folderRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '10px',
    padding: '8px 10px',
    backgroundColor: tokens.colorNeutralBackground2,
    ...shorthands.borderRadius(tokens.borderRadiusMedium),
    border: `1px solid ${tokens.colorNeutralStroke2}`
  },
  folderRowGap: {
    marginTop: SPACE.tight
  },
  folderIcon: {
    fontSize: `${ICON.control}px`,
    flexShrink: 0,
    color: tokens.colorCompoundBrandForeground1
  },
  folderCol: {
    display: 'flex',
    flexDirection: 'column',
    minWidth: 0,
    flexGrow: 1
  },
  folderLabel: {
    fontWeight: tokens.fontWeightSemibold,
    color: tokens.colorNeutralForeground1
  },
  folderPath: {
    color: tokens.colorNeutralForeground3,
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap'
  },
  // Media-components setup box (download/locate ffmpeg on first run).
  setupBox: {
    display: 'flex',
    flexDirection: 'column',
    gap: '10px',
    padding: '12px',
    backgroundColor: tokens.colorNeutralBackground2,
    ...shorthands.borderRadius(tokens.borderRadiusMedium),
    border: `1px solid ${tokens.colorNeutralStroke2}`
  },
  setupRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '8px'
  },
  setupButtons: {
    display: 'flex',
    flexWrap: 'wrap',
    gap: '8px'
  },
  setupReadyIcon: {
    fontSize: `${ICON.control}px`,
    flexShrink: 0,
    color: tokens.colorStatusSuccessForeground1
  },
  tips: {
    display: 'flex',
    flexDirection: 'column',
    gap: '10px'
  },
  tip: {
    display: 'flex',
    alignItems: 'flex-start',
    gap: '10px'
  },
  tipIcon: {
    fontSize: `${ICON.control}px`,
    flexShrink: 0,
    marginTop: SPACE.hairline,
    color: tokens.colorCompoundBrandForeground1
  }
})

const TIPS: { icon: React.JSX.Element; text: string }[] = [
  {
    icon: <ClipboardPasteRegular />,
    text: 'Turn on clipboard detection in Settings and AeroFetch will offer to fetch links you copy.'
  },
  {
    icon: <HistoryRegular />,
    text: 'Downloads queue with a concurrency cap, and every completed file lands in History.'
  },
  {
    icon: <OptionsRegular />,
    text: 'Subtitles, SponsorBlock, custom yt-dlp commands, and more live in Settings.'
  },
  {
    icon: <KeyboardRegular />,
    text: 'Press Ctrl+K anytime to jump to any screen or start a new download.'
  }
]

export function Onboarding(): React.JSX.Element {
  const styles = useStyles()
  const errText = useErrorTextStyles()
  const update = useSettings((s) => s.update)
  const videoFolder = useSettings((s) => s.videoFolder)
  const audioFolder = useSettings((s) => s.audioFolder)
  const chooseFolder = useSettings((s) => s.chooseFolder)
  // A brand-new user gets the full welcome; an already-onboarded user only lands here
  // because ffmpeg is missing (e.g. upgrading from a bundled build) — show a compact
  // "finish setup" card that auto-dismisses once the tools are installed.
  const isFresh = !useSettings((s) => s.hasCompletedOnboarding)

  const ready = useSetup((s) => s.ffmpegReady)
  const phase = useSetup((s) => s.phase)
  const fraction = useSetup((s) => s.fraction)
  const busy = useSetup((s) => s.busy)
  const setupError = useSetup((s) => s.error)
  const download = useSetup((s) => s.download)
  const cancel = useSetup((s) => s.cancel)
  const locate = useSetup((s) => s.locate)

  const componentsField = (
    <Field label="Media components">
      <div className={styles.setupBox}>
        {ready === true ? (
          <div className={styles.setupRow}>
            <CheckmarkCircleFilled className={styles.setupReadyIcon} />
            <Caption1>ffmpeg and ffprobe are installed and ready.</Caption1>
          </div>
        ) : ready === null ? (
          <div className={styles.setupRow}>
            <Spinner size="tiny" />
            <Caption1>Checking media components…</Caption1>
          </div>
        ) : (
          <>
            <Caption1 className={styles.folderNote}>
              AeroFetch uses ffmpeg to merge and convert media. It isn&apos;t bundled — download it
              once (about 105 MB) and it&apos;s kept across updates. On an offline machine, point
              AeroFetch at an ffmpeg you already have.
            </Caption1>
            {busy ? (
              <>
                <ProgressBar
                  value={phase === 'extracting' ? undefined : fraction}
                  aria-label="ffmpeg setup progress"
                />
                <div className={styles.setupRow}>
                  <Caption1 className={styles.folderNote}>
                    {phase === 'extracting' ? 'Unpacking…' : 'Downloading ffmpeg…'}
                  </Caption1>
                  {/* Only the download is cancelable — unpacking runs to completion. */}
                  {phase === 'downloading' && (
                    <Button
                      size="small"
                      appearance="subtle"
                      icon={<DismissRegular />}
                      onClick={cancel}
                    >
                      Cancel
                    </Button>
                  )}
                </div>
              </>
            ) : (
              <div className={styles.setupButtons}>
                <Button
                  appearance="primary"
                  icon={<ArrowDownloadRegular />}
                  onClick={() => void download()}
                >
                  Download components
                </Button>
                <Button icon={<FolderRegular />} onClick={() => void locate()}>
                  Locate existing ffmpeg…
                </Button>
              </div>
            )}
            {setupError && <Caption1 className={errText.errorPre}>{setupError}</Caption1>}
          </>
        )}
      </div>
    </Field>
  )

  return (
    <div className={styles.root}>
      <Card className={styles.card}>
        <div className={styles.brandRow}>
          <div className={styles.mark}>
            <ArrowDownloadFilled />
          </div>
          <Title2 as="h1">{isFresh ? 'Welcome to AeroFetch' : 'Finish setup'}</Title2>
        </div>

        {isFresh ? (
          <Body1>
            A no-frills frontend for yt-dlp: paste a link, pick a quality, and download video or
            audio. yt-dlp is bundled; ffmpeg is set up once below.
          </Body1>
        ) : (
          <Body1>
            AeroFetch needs ffmpeg and ffprobe to process downloads. They aren&apos;t bundled — set
            them up once to continue.
          </Body1>
        )}

        {isFresh && (
          <Field label="Where downloads go">
            <Caption1 className={styles.folderNote}>
              Videos and audio save to your Documents folders by default. Pick a different folder
              now, or change it any time in Settings.
            </Caption1>
            <div className={styles.folderRow}>
              <VideoClipRegular className={styles.folderIcon} />
              <div className={styles.folderCol}>
                <Caption1 className={styles.folderLabel}>Video</Caption1>
                <Caption1 className={styles.folderPath} title={videoFolder || 'Documents\\Video'}>
                  {videoFolder || 'Documents\\Video'}
                </Caption1>
              </div>
              <Button
                size="small"
                icon={<FolderRegular />}
                onClick={() => chooseFolder('videoFolder')}
              >
                Choose…
              </Button>
            </div>
            <div className={mergeClasses(styles.folderRow, styles.folderRowGap)}>
              <MusicNote2Regular className={styles.folderIcon} />
              <div className={styles.folderCol}>
                <Caption1 className={styles.folderLabel}>Audio</Caption1>
                <Caption1 className={styles.folderPath} title={audioFolder || 'Documents\\Audio'}>
                  {audioFolder || 'Documents\\Audio'}
                </Caption1>
              </div>
              <Button
                size="small"
                icon={<FolderRegular />}
                onClick={() => chooseFolder('audioFolder')}
              >
                Choose…
              </Button>
            </div>
          </Field>
        )}

        {componentsField}

        {isFresh && (
          <>
            <div className={styles.tips}>
              {TIPS.map((tip) => (
                <div key={tip.text} className={styles.tip}>
                  <span className={styles.tipIcon}>{tip.icon}</span>
                  <Caption1>{tip.text}</Caption1>
                </div>
              ))}
            </div>

            <Button
              appearance="primary"
              icon={<RocketRegular />}
              disabled={ready !== true}
              onClick={() => update({ hasCompletedOnboarding: true })}
            >
              Get started
            </Button>
          </>
        )}
      </Card>
    </div>
  )
}
