import { memo } from 'react'
import {
  Text,
  Caption1,
  Button,
  ProgressBar,
  Spinner,
  makeStyles,
  mergeClasses,
  tokens,
  shorthands
} from '@fluentui/react-components'
import {
  DismissRegular,
  DeleteRegular,
  OpenRegular,
  FolderRegular,
  ArrowClockwiseRegular,
  ArrowDownloadRegular,
  ArrowUpRegular,
  BookmarkRegular,
  PauseRegular,
  PlayRegular,
  CheckmarkCircleFilled,
  ErrorCircleFilled,
  EyeOffRegular
} from '@fluentui/react-icons'
import { useShallow } from 'zustand/react/shallow'
import { useDownloads, type DownloadItem } from '../store/downloads'
import { thumbUrl } from '../lib/thumb'
import { fmtSchedule } from '../lib/datetime'
import { fmtSpeed, fmtEta } from '@shared/format'
import { MediaThumb } from './MediaThumb'
import { Hint } from './Hint'
import { StatusChip } from './ui/StatusChip'
import { useFocusStyles } from './ui/focusRing'
import { useTextStyles } from './ui/text'
import { SPACE, RADIUS, ICON, META_SEP } from './ui/tokens'
import { THUMB_MD } from '../lib/thumbSizes'

const useStyles = makeStyles({
  root: {
    display: 'flex',
    gap: '14px',
    // List-item card: card padding + list-item radius (UI3/UI7).
    padding: SPACE.section,
    backgroundColor: tokens.colorNeutralBackground1,
    ...shorthands.borderRadius(RADIUS.surface),
    border: `1px solid ${tokens.colorNeutralStroke2}`
  },
  thumb: {
    flexShrink: 0,
    width: `${THUMB_MD.w}px`,
    height: `${THUMB_MD.h}px`,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    // One thumbnail radius app-wide (UI6): control tier / Medium.
    ...shorthands.borderRadius(RADIUS.control)
  },
  body: {
    flexGrow: 1,
    minWidth: 0,
    display: 'flex',
    flexDirection: 'column',
    gap: '4px'
  },
  titleRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '8px'
  },
  progressRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '10px',
    marginTop: SPACE.xtight
  },
  progressBar: {
    flexGrow: 1
  },
  stats: {
    color: tokens.colorNeutralForeground3,
    whiteSpace: 'nowrap'
  },
  error: {
    color: tokens.colorPaletteRedForeground1
  },
  actions: {
    display: 'flex',
    alignItems: 'center',
    gap: SPACE.xtight,
    flexShrink: 0,
    // Icon-only row actions get a >=40px hit target for touch/pen (W16); the
    // glyph stays its normal size, the subtle button just carries more padding.
    '& button': {
      minWidth: '40px',
      minHeight: '40px'
    }
  }
})

function pct(progress: number): string {
  return `${Math.round(progress * 100)}%`
}

export const QueueItem = memo(function QueueItem({
  item
}: {
  item: DownloadItem
}): React.JSX.Element {
  const styles = useStyles()
  const focus = useFocusStyles()
  const text = useTextStyles()
  // One shallow-compared selection instead of 10 separate subscriptions per row
  // (L163). The actions are stable, so this never re-renders from the store.
  const {
    cancel,
    pause,
    resume,
    prioritize,
    saveForLater,
    queueNow,
    remove,
    retry,
    openFile,
    showInFolder
  } = useDownloads(
    useShallow((s) => ({
      cancel: s.cancel,
      pause: s.pause,
      resume: s.resume,
      prioritize: s.prioritize,
      saveForLater: s.saveForLater,
      queueNow: s.queueNow,
      remove: s.remove,
      retry: s.retry,
      openFile: s.openFile,
      showInFolder: s.showInFolder
    }))
  )

  const active = item.status === 'downloading' || item.status === 'queued'

  // W7: Delete on a focused row removes it -- cancelling first if it's still running,
  // since an in-flight download can't just be dropped from the list. Only when the
  // row itself holds focus, so Delete on one of its action buttons is unaffected.
  function onKeyDown(e: React.KeyboardEvent): void {
    if (e.key === 'Delete' && e.target === e.currentTarget) {
      e.preventDefault()
      if (active) cancel(item.id)
      else remove(item.id)
    }
  }

  // Format the raw progress numbers for display (H4: main sends bytes/sec + secs,
  // the renderer owns formatting via the one shared formatter).
  const speedLabel = fmtSpeed(item.speedBytesPerSec)
  const etaLabel = fmtEta(item.etaSeconds)

  // L55: a probed-format quality label already carries the size ("720p · mp4 ·
  // 184 MB"); skip sizeLabel when it's already embedded to avoid showing it twice.
  const sizeAlreadyInQuality = item.sizeLabel && item.quality.includes(item.sizeLabel)
  const metaParts = [
    item.channel,
    item.durationLabel,
    item.quality,
    item.kind === 'audio' ? 'Audio' : 'Video',
    !sizeAlreadyInQuality ? item.sizeLabel : undefined
  ].filter(Boolean)

  return (
    <div className={mergeClasses(styles.root, focus.focusRing)} tabIndex={0} onKeyDown={onKeyDown}>
      <MediaThumb
        className={styles.thumb}
        src={thumbUrl({ thumbnail: item.thumbnail, url: item.url })}
        kind={item.kind}
        iconSize={28}
      />

      <div className={styles.body}>
        <div className={styles.titleRow}>
          {item.status === 'completed' && (
            <CheckmarkCircleFilled
              fontSize={ICON.inline}
              style={{ color: tokens.colorPaletteGreenForeground1, flexShrink: 0 }}
            />
          )}
          {item.status === 'error' && (
            <ErrorCircleFilled
              fontSize={ICON.inline}
              style={{ color: tokens.colorPaletteRedForeground1, flexShrink: 0 }}
            />
          )}
          <Text className={text.title}>{item.title}</Text>
          <StatusChip status={item.status} />
          {item.incognito && (
            <Hint label="Private -- not saved to history" placement="top" align="start">
              <EyeOffRegular
                fontSize={ICON.inline}
                style={{ color: tokens.colorNeutralForeground3 }}
              />
            </Hint>
          )}
        </div>

        <Caption1 className={text.muted}>{metaParts.join(META_SEP)}</Caption1>

        {item.status === 'downloading' && (
          <div className={styles.progressRow}>
            {/* Indeterminate when finishing (the second stream / merge reads as
                "working" rather than a 0→100% restart, SR7) or when yt-dlp can't
                report a total size, so the bar never sits frozen at 0% (L137). */}
            <ProgressBar
              className={styles.progressBar}
              value={item.finishing || item.sizeUnknown ? undefined : item.progress}
              thickness="large"
              aria-label={`Download progress for ${item.title ?? item.url}`}
            />
            <Caption1 className={styles.stats}>
              {item.finishing ? (
                'Finishing…'
              ) : (
                <>
                  {item.sizeUnknown ? 'Downloading…' : pct(item.progress)}
                  {speedLabel ? `${META_SEP}${speedLabel}` : ''}
                  {etaLabel ? `${META_SEP}${etaLabel} left` : ''}
                </>
              )}
            </Caption1>
          </div>
        )}

        {item.status === 'queued' && (
          <div className={styles.progressRow}>
            <Spinner size="tiny" />
            <Caption1 className={styles.stats}>Waiting to start…</Caption1>
          </div>
        )}

        {item.status === 'paused' && (
          <div className={styles.progressRow}>
            <ProgressBar
              className={styles.progressBar}
              value={item.progress}
              thickness="large"
              aria-label={`Download progress for ${item.title ?? item.url}`}
            />
            <Caption1 className={styles.stats}>
              Paused{META_SEP}
              {pct(item.progress)}
            </Caption1>
          </div>
        )}

        {item.status === 'saved' && (
          <Caption1 className={styles.stats}>
            {item.scheduledFor
              ? `Scheduled for ${fmtSchedule(item.scheduledFor)}`
              : 'Saved for later'}
          </Caption1>
        )}

        {item.status === 'error' && item.error && (
          <Caption1 className={styles.error}>{item.error}</Caption1>
        )}
      </div>

      <div className={styles.actions}>
        {item.status === 'downloading' && (
          <Hint label="Pause" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<PauseRegular />}
              onClick={() => pause(item.id)}
              aria-label="Pause"
            />
          </Hint>
        )}

        {item.status === 'queued' && (
          <>
            <Hint label="Download next" placement="top" align="end">
              <Button
                appearance="subtle"
                icon={<ArrowUpRegular />}
                onClick={() => prioritize(item.id)}
                aria-label="Download next"
              />
            </Hint>
            <Hint label="Save for later" placement="top" align="end">
              <Button
                appearance="subtle"
                icon={<BookmarkRegular />}
                onClick={() => saveForLater(item.id)}
                aria-label="Save for later"
              />
            </Hint>
          </>
        )}

        {item.status === 'paused' && (
          <Hint label="Resume" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<PlayRegular />}
              onClick={() => resume(item.id)}
              aria-label="Resume"
            />
          </Hint>
        )}

        {item.status === 'saved' && (
          <Hint label="Add to queue" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<ArrowDownloadRegular />}
              onClick={() => queueNow(item.id)}
              aria-label="Add to queue"
            />
          </Hint>
        )}

        {active && (
          <Hint label="Cancel" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<DismissRegular />}
              onClick={() => cancel(item.id)}
              aria-label="Cancel"
            />
          </Hint>
        )}

        {item.status === 'completed' && (
          <>
            <Hint label="Open file" placement="top" align="end">
              <Button
                appearance="subtle"
                icon={<OpenRegular />}
                onClick={() => openFile(item.id)}
                aria-label="Open file"
              />
            </Hint>
            <Hint label="Show in folder" placement="top" align="end">
              <Button
                appearance="subtle"
                icon={<FolderRegular />}
                onClick={() => showInFolder(item.id)}
                aria-label="Show in folder"
              />
            </Hint>
          </>
        )}

        {(item.status === 'error' || item.status === 'canceled') && (
          <Hint label="Retry" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<ArrowClockwiseRegular />}
              onClick={() => retry(item.id)}
              aria-label="Retry"
            />
          </Hint>
        )}

        {!active && (
          <Hint label="Remove" placement="top" align="end">
            <Button
              appearance="subtle"
              icon={<DeleteRegular />}
              onClick={() => remove(item.id)}
              aria-label="Remove"
            />
          </Hint>
        )}
      </div>
    </div>
  )
})
