import {
  Input,
  Textarea,
  Field,
  Button,
  Checkbox,
  Spinner,
  Text,
  Caption1,
  mergeClasses
} from '@fluentui/react-components'
import {
  ArrowDownloadRegular,
  ClipboardPasteRegular,
  SearchRegular,
  VideoClipRegular,
  MusicNote2Regular,
  ErrorCircleRegular,
  LibraryRegular,
  DismissRegular,
  CutRegular,
  CalendarClockRegular,
  WarningRegular,
  SettingsRegular,
  WindowConsoleRegular
} from '@fluentui/react-icons'
import { useEffect, useRef } from 'react'
import { type MediaKind } from '../store/downloads'
import { useNav } from '../store/nav'
import { QUALITY_OPTIONS } from '../lib/qualityOptions'
import { Select } from './Select'
import { Hint } from './Hint'
import { SegmentedControl } from './ui/SegmentedControl'
import { Banner } from './ui/Banner'
import { LinkSuggestion } from './ui/LinkSuggestion'
import { useTextStyles } from './ui/text'
import { META_SEP } from './ui/tokens'
import { DownloadOptionsForm } from './DownloadOptionsForm'
import { useDownloadBarStyles } from './downloadBar/styles'
import { useDownloadBar, toLocalDatetimeValue } from './downloadBar/useDownloadBar'
import { PlaylistPanel } from './downloadBar/PlaylistPanel'

export function DownloadBar(): React.JSX.Element {
  const styles = useDownloadBarStyles()
  const text = useTextStyles()
  const bar = useDownloadBar()
  // Register how to focus the URL field so App can request focus (launch / "New
  // download") without a hardcoded getElementById into this markup (L118).
  const urlInputRef = useRef<HTMLInputElement>(null)
  const registerUrlFocuser = useNav((s) => s.registerUrlFocuser)
  useEffect(() => {
    registerUrlFocuser(() => urlInputRef.current?.focus())
    return () => registerUrlFocuser(null)
  }, [registerUrlFocuser])
  const {
    url,
    kind,
    quality,
    showTrim,
    trim,
    showSchedule,
    scheduleAt,
    dragActive,
    dup,
    dupInHistory,
    showAdvanced,
    downloadOptions,
    incognito,
    commandPreview,
    previewLoading,
    info,
    thumbFailed,
    probing,
    probeError,
    usingFormats,
    selectedFormat,
    playlist,
    selected,
    allSelected,
    suggestion,
    suggestionSource,
    channelHint
  } = bar

  return (
    <div
      className={mergeClasses(styles.root, dragActive && styles.rootDragging)}
      onDragEnter={bar.onDragEnter}
      onDragOver={bar.onDragOver}
      onDragLeave={bar.onDragLeave}
      onDrop={bar.onDrop}
    >
      <div className={styles.urlRow}>
        <Input
          className={styles.url}
          input={{ ref: urlInputRef, 'aria-label': 'Video or playlist URL' }}
          value={url}
          onChange={(_, d) => bar.onUrlChange(d.value)}
          onKeyDown={(e) => {
            if (e.key !== 'Enter') return
            // Enter is "go": start the download (or add a fetched playlist). Preview
            // formats stays an explicit, optional click on the button (UX2).
            if (playlist) {
              if (selected.size > 0) bar.addPlaylist()
            } else bar.download()
          }}
          placeholder="Paste a video or playlist URL, then press Enter to download"
          size="large"
          contentBefore={<ArrowDownloadRegular />}
        />
        <Hint label="Preview available formats (optional)" placement="bottom" align="end">
          <Button
            size="large"
            icon={probing ? <Spinner size="tiny" /> : <SearchRegular />}
            onClick={bar.fetchFormats}
            disabled={!url.trim() || probing}
            aria-label="Preview available formats (optional)"
          />
        </Hint>
        <Hint label="Paste from clipboard" placement="bottom" align="end">
          <Button
            size="large"
            icon={<ClipboardPasteRegular />}
            onClick={bar.paste}
            aria-label="Paste from clipboard"
          />
        </Hint>
      </div>

      {suggestion && (
        <LinkSuggestion
          prefix={suggestionSource === 'external' ? 'Link received: ' : 'Use copied link? '}
          link={suggestion}
          onAccept={bar.acceptSuggestion}
          onDismiss={bar.dismissSuggestion}
          dismissLabel="Dismiss suggested link"
        />
      )}

      {channelHint && (
        <Banner
          icon={<LibraryRegular />}
          wrap
          actions={
            <>
              <Button size="small" appearance="primary" onClick={bar.openInLibrary}>
                Open in Library
              </Button>
              <Button
                size="small"
                appearance="subtle"
                icon={<DismissRegular />}
                onClick={bar.dismissChannelHint}
                aria-label="Dismiss Library suggestion"
              />
            </>
          }
        >
          <Caption1>
            This looks like a channel or playlist. Add it in the Library to download many videos at
            once.
          </Caption1>
        </Banner>
      )}

      {dup && (
        <Banner
          tone="warning"
          icon={<WarningRegular />}
          actions={
            <>
              <Button size="small" appearance="primary" onClick={bar.downloadAnyway}>
                Download anyway
              </Button>
              <Button
                size="small"
                appearance="subtle"
                icon={<DismissRegular />}
                onClick={() => bar.setDup(null)}
                aria-label="Dismiss duplicate warning"
              />
            </>
          }
        >
          <Caption1>
            {dupInHistory ? 'Already downloaded' : 'Already in your queue'}: "{dup}".
          </Caption1>
        </Banner>
      )}

      {probing && (
        <div className={styles.statusRow}>
          <Spinner size="tiny" />
          <Caption1>Fetching…</Caption1>
        </div>
      )}

      {probeError && (
        <div className={mergeClasses(styles.statusRow, styles.errorRow)}>
          <ErrorCircleRegular />
          <Caption1>{probeError} -- you can still download with the presets below.</Caption1>
        </div>
      )}

      {info && (
        <div className={styles.preview}>
          {info.thumbnail && thumbFailed !== info.thumbnail ? (
            <img
              className={styles.previewThumb}
              src={info.thumbnail}
              alt=""
              onError={() => bar.setThumbFailed(info.thumbnail ?? null)}
            />
          ) : (
            <div className={styles.previewThumb}>
              {kind === 'audio' ? (
                <MusicNote2Regular fontSize={28} />
              ) : (
                <VideoClipRegular fontSize={28} />
              )}
            </div>
          )}
          <div className={styles.previewBody}>
            <Text className={text.title}>{info.title}</Text>
            <Caption1 className={text.muted}>
              {[info.channel, info.durationLabel].filter(Boolean).join(META_SEP)}
            </Caption1>
          </div>
        </div>
      )}

      {playlist && (
        <PlaylistPanel
          playlist={playlist}
          selected={selected}
          allSelected={allSelected}
          onToggleAll={bar.toggleAll}
          onSetAllKinds={bar.setAllKinds}
          onToggleEntry={bar.toggleEntry}
          effKind={bar.effKind}
          onToggleItemKind={bar.toggleItemKind}
          formatExpanded={bar.formatExpanded}
          itemFormatOptions={bar.itemFormatOptions}
          itemFormat={bar.itemFormat}
          formatProbing={bar.formatProbing}
          formatProbeError={bar.formatProbeError}
          onToggleFormat={bar.toggleItemFormat}
          onSetItemFormat={bar.setItemFormat}
        />
      )}

      {!playlist && (
        <div className={styles.trimBlock}>
          <div className={styles.optButtons}>
            <Button
              size="small"
              appearance="subtle"
              icon={<CutRegular />}
              onClick={() => bar.setShowTrim((v) => !v)}
            >
              {trim.trim() ? 'Trim · on' : 'Trim'}
            </Button>
            <Button
              size="small"
              appearance="subtle"
              icon={<CalendarClockRegular />}
              onClick={() => bar.setShowSchedule((v) => !v)}
            >
              {scheduleAt ? 'Scheduled' : 'Schedule'}
            </Button>
          </div>
          {showTrim && (
            <div className={styles.trimPanel}>
              <Field
                label="Sections to keep"
                hint="Time ranges like 1:30-2:00 -- one per line or comma-separated. Leave empty to download the whole thing."
              >
                <Textarea
                  value={trim}
                  onChange={(_, d) => bar.onTrimChange(d.value)}
                  placeholder={'0:30-1:45\n3:00-3:30'}
                  resize="vertical"
                />
              </Field>
            </div>
          )}
          {showSchedule && (
            <div className={styles.trimPanel}>
              <Field
                label="Start at"
                hint="Pick a date and time to start this download. Leave empty to start now. Scheduled downloads only fire while AeroFetch is running."
              >
                <input
                  type="datetime-local"
                  className={styles.dtInput}
                  value={scheduleAt}
                  min={toLocalDatetimeValue(new Date())}
                  onChange={(e) => bar.setScheduleAt(e.target.value)}
                />
              </Field>
            </div>
          )}
        </div>
      )}

      {!playlist && (
        <div className={styles.commandBlock}>
          <div className={styles.optButtons}>
            <Button
              size="small"
              appearance="subtle"
              icon={<SettingsRegular />}
              onClick={() => bar.setShowAdvanced((v) => !v)}
            >
              {showAdvanced ? 'Advanced · on' : 'Advanced'}
            </Button>
            <Button
              size="small"
              appearance="subtle"
              icon={previewLoading ? <Spinner size="tiny" /> : <WindowConsoleRegular />}
              onClick={bar.toggleCommandPreview}
              disabled={!url.trim() || previewLoading}
            >
              {commandPreview ? 'Hide command' : 'Show command'}
            </Button>
          </div>
          {commandPreview && (
            <div className={styles.commandPreviewPanel}>
              {commandPreview.ok ? (
                commandPreview.command
              ) : (
                <span className={styles.commandError}>Error: {commandPreview.error}</span>
              )}
            </div>
          )}
          {showAdvanced && (
            <div className={styles.optionsPanel}>
              <Checkbox
                checked={incognito}
                onChange={(_, d) => bar.setIncognito(!!d.checked)}
                label="Incognito mode (no logging, no history, no cookies)"
              />
              <DownloadOptionsForm
                value={downloadOptions}
                onChange={bar.onDownloadOptionsChange}
                kind={kind}
              />
            </div>
          )}
        </div>
      )}

      <div className={styles.controls}>
        <div className={styles.control}>
          <Caption1>Format</Caption1>
          <SegmentedControl<MediaKind>
            value={kind}
            options={[
              { value: 'video', label: 'Video' },
              { value: 'audio', label: 'Audio' }
            ]}
            onChange={bar.onKindChange}
            ariaLabel="Format"
          />
        </div>

        <div className={styles.control}>
          {/* The label stays "Quality" in both states (UX18) — the fetched tag,
              not a morphing label, signals that the list now shows the site's
              real formats. */}
          <Caption1>
            Quality
            {usingFormats && <span className={styles.qualityFetched}> • fetched</span>}
          </Caption1>
          {usingFormats ? (
            <Select
              className={styles.quality}
              aria-label="Quality (fetched formats)"
              size="large"
              value={selectedFormat?.id ?? ''}
              options={(info?.formats ?? []).map((f) => ({ value: f.id, label: f.label }))}
              onChange={bar.onFormatIdChange}
            />
          ) : (
            <Select
              className={styles.quality}
              aria-label="Quality"
              size="large"
              value={quality}
              options={QUALITY_OPTIONS[kind].map((q) => ({ value: q, label: q }))}
              onChange={bar.onQualityChange}
            />
          )}
        </div>

        <div className={styles.spacer} />

        {playlist ? (
          <Button
            appearance="primary"
            size="large"
            icon={<ArrowDownloadRegular />}
            onClick={bar.addPlaylist}
            disabled={selected.size === 0}
          >
            Add {selected.size} to queue
          </Button>
        ) : (
          <Button
            appearance="primary"
            size="large"
            icon={scheduleAt ? <CalendarClockRegular /> : <ArrowDownloadRegular />}
            onClick={bar.download}
            disabled={!url.trim()}
          >
            {scheduleAt ? 'Schedule' : 'Download'}
          </Button>
        )}
      </div>
    </div>
  )
}
