import { Button, Checkbox, Caption1, Spinner, mergeClasses } from '@fluentui/react-components'
import {
  AppsListRegular,
  VideoClipRegular,
  MusicNote2Regular,
  OptionsRegular
} from '@fluentui/react-icons'
import { BEST_FORMAT_ID, type FormatOption, type PlaylistInfo } from '@shared/ipc'
import { type MediaKind } from '../../store/downloads'
import { type ChosenFormat } from '../../store/downloadTypes'
import { Hint } from '../Hint'
import { Select } from '../Select'
import { IconButton } from '../ui/IconButton'
import { useTextStyles } from '../ui/text'
import { META_SEP } from '../ui/tokens'
import { useDownloadBarStyles } from './styles'

interface PlaylistPanelProps {
  playlist: PlaylistInfo
  selected: Set<number>
  allSelected: boolean
  onToggleAll: () => void
  onSetAllKinds: (k: MediaKind) => void
  onToggleEntry: (index: number, on: boolean) => void
  effKind: (index: number) => MediaKind
  onToggleItemKind: (index: number) => void
  // per-item exact-format picker (video rows only)
  formatExpanded: Set<number>
  itemFormatOptions: Record<number, FormatOption[]>
  itemFormat: (index: number) => ChosenFormat | undefined
  formatProbing: Set<number>
  formatProbeError: Record<number, string>
  onToggleFormat: (index: number) => void
  onSetItemFormat: (index: number, formatId: string) => void
}

export function PlaylistPanel({
  playlist,
  selected,
  allSelected,
  onToggleAll,
  onSetAllKinds,
  onToggleEntry,
  effKind,
  onToggleItemKind,
  formatExpanded,
  itemFormatOptions,
  itemFormat,
  formatProbing,
  formatProbeError,
  onToggleFormat,
  onSetItemFormat
}: PlaylistPanelProps): React.JSX.Element {
  const styles = useDownloadBarStyles()
  const text = useTextStyles()
  return (
    <div className={styles.plPanel}>
      <div className={styles.plHeader}>
        <AppsListRegular />
        <Caption1 className={mergeClasses(styles.plHeaderGrow, text.title)}>
          {playlist.title}
          {playlist.uploader ? `${META_SEP}${playlist.uploader}` : ''}
        </Caption1>
        <Caption1 className={text.muted}>
          {selected.size} of {playlist.count} selected
        </Caption1>
        <Button size="small" appearance="subtle" onClick={onToggleAll}>
          {allSelected ? 'Select none' : 'Select all'}
        </Button>
        <Button size="small" appearance="subtle" onClick={() => onSetAllKinds('video')}>
          All video
        </Button>
        <Button size="small" appearance="subtle" onClick={() => onSetAllKinds('audio')}>
          All audio
        </Button>
      </div>
      <div className={styles.plList}>
        {playlist.entries.map((e) => {
          const isVideo = effKind(e.index) === 'video'
          const chosen = itemFormat(e.index)
          const expanded = formatExpanded.has(e.index)
          const probing = formatProbing.has(e.index)
          const error = formatProbeError[e.index]
          const options = itemFormatOptions[e.index]
          return (
            <div key={e.index} className={styles.plItemGroup}>
              <div className={styles.plItemRow}>
                <Checkbox
                  className={styles.plItem}
                  checked={selected.has(e.index)}
                  onChange={(_, d) => onToggleEntry(e.index, !!d.checked)}
                  label={
                    <span className={styles.plItemLabel}>
                      <span className={text.truncate}>
                        {e.index}. {e.title}
                      </span>
                      {(e.durationLabel || e.uploader || chosen) && (
                        <Caption1 className={text.muted}>
                          {[e.durationLabel, e.uploader, chosen?.label]
                            .filter(Boolean)
                            .join(META_SEP)}
                        </Caption1>
                      )}
                    </span>
                  }
                />
                {isVideo && (
                  <Hint
                    label={expanded ? 'Hide format' : 'Choose exact format'}
                    placement="top"
                    align="end"
                  >
                    <IconButton
                      size="sm"
                      style={{ flexShrink: 0 }}
                      className={chosen ? styles.plFormatBtnActive : undefined}
                      aria-pressed={expanded}
                      icon={<OptionsRegular />}
                      onClick={() => onToggleFormat(e.index)}
                      aria-label={`Choose format for ${e.title}`}
                    />
                  </Hint>
                )}
                <Hint
                  label={
                    effKind(e.index) === 'audio'
                      ? 'Audio -- click for video'
                      : 'Video -- click for audio'
                  }
                  placement="top"
                  align="end"
                >
                  <IconButton
                    size="sm"
                    style={{ flexShrink: 0 }}
                    icon={
                      effKind(e.index) === 'audio' ? <MusicNote2Regular /> : <VideoClipRegular />
                    }
                    onClick={() => onToggleItemKind(e.index)}
                    aria-label={`Download type for ${e.title}: ${effKind(e.index)}`}
                  />
                </Hint>
              </div>
              {isVideo && expanded && (
                <div className={styles.plFormatPanel}>
                  {probing ? (
                    <Caption1 className={styles.plFormatStatus}>
                      <Spinner size="tiny" /> Fetching formats…
                    </Caption1>
                  ) : error ? (
                    <Caption1 className={styles.plFormatError}>{error}</Caption1>
                  ) : options && options.length > 0 ? (
                    <Select
                      className={styles.plFormatSelect}
                      aria-label={`Format for ${e.title}`}
                      value={chosen?.id ?? BEST_FORMAT_ID}
                      options={options.map((o) => ({ value: o.id, label: o.label }))}
                      onChange={(v) => onSetItemFormat(e.index, v)}
                    />
                  ) : (
                    <Caption1 className={text.muted}>No selectable formats.</Caption1>
                  )}
                </div>
              )}
            </div>
          )
        })}
      </div>
    </div>
  )
}
