import React from 'react';
import type {
  StreamFileMetadata,
  TransferHandle,
  TransferProgress,
} from '@shade/sdk';
import { useShadeRuntimeTheme } from '../../ShadeRuntimeProvider.js';
import { useThumbnail } from '../../useShadeThumbnails.js';
import { ProgressBar } from './ProgressBar.js';
import { SpeedReadout } from './SpeedReadout.js';
import { ETAReadout } from './ETAReadout.js';
import { LaneIndicator } from './LaneIndicator.js';
import { ThumbnailPreview } from './ThumbnailPreview.js';

export interface TransferRowProps {
  handle: TransferHandle;
  progress: TransferProgress | null;
  /** Optional file name to display. */
  name?: string;
  /** Total bytes for this transfer (used to render percent when progress lacks it). */
  bytesTotal?: number;
  done?: boolean;
  error?: unknown;
  onCancel?: () => void;
  onDismiss?: () => void;
  /**
   * V3.9 — render a 48×48 preview to the left of the row when the main
   * stream's `fileMetadata` references a thumbnail-stream that has
   * arrived in the cache. Off by default (rows stay compact in chat
   * lists); turn it on per row, or wrap in `<ShadeThumbnailProvider />`
   * + flip on at the row level for a file-browser-style UI.
   */
  showThumbnail?: boolean;
  /**
   * V3.9 — `fileMetadata` from the main `stream-init`. Required when
   * `showThumbnail` is true; the row reads `thumbnailStreamId` /
   * `thumbnailHash` to consult the cache.
   */
  fileMetadata?: StreamFileMetadata;
  /** Thumbnail edge in CSS px (default 48). */
  thumbnailSize?: number;
  className?: string;
  style?: React.CSSProperties;
}

/** Default UI for a single transfer. Replace via render-prop on the parent. */
export function TransferRow({
  handle,
  progress,
  name,
  bytesTotal,
  done,
  error,
  onCancel,
  onDismiss,
  showThumbnail,
  fileMetadata,
  thumbnailSize,
  className,
  style,
}: TransferRowProps): React.ReactElement {
  const theme = useShadeRuntimeTheme();
  const percent =
    progress?.percent ??
    (bytesTotal !== undefined && progress !== null ? progress.bytesSent / bytesTotal : undefined);
  const errorMessage =
    error instanceof Error ? error.message : error !== undefined ? String(error) : null;

  const thumb = useThumbnail(
    showThumbnail === true ? fileMetadata?.thumbnailStreamId : undefined,
    showThumbnail === true ? fileMetadata?.thumbnailHash : undefined,
  );

  const displayName = name ?? fileMetadata?.filename ?? handle.streamId;

  return (
    <div
      className={className}
      style={{
        display: 'flex',
        flexDirection: 'column',
        gap: 6,
        padding: 12,
        background: theme.bgElevated,
        border: `1px solid ${theme.border}`,
        borderRadius: theme.radius,
        fontFamily: theme.font,
        color: theme.text,
        ...style,
      }}
    >
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        {showThumbnail === true ? (
          <ThumbnailPreview
            bytes={thumb?.bytes ?? null}
            mime={thumb?.mime ?? null}
            size={thumbnailSize ?? 48}
          />
        ) : null}
        <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minWidth: 0 }}>
          <span
            style={{
              fontSize: 13,
              color: errorMessage !== null ? theme.danger : theme.text,
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
            }}
            title={displayName}
          >
            {displayName}
          </span>
          {fileMetadata?.mimeType !== undefined && fileMetadata.mimeType.length > 0 ? (
            <span style={{ fontSize: 11, color: theme.textMuted }}>
              {fileMetadata.mimeType}
            </span>
          ) : null}
        </div>
        {progress !== null ? (
          <LaneIndicator lanes={progress.lanes} />
        ) : null}
        {!done && onCancel !== undefined ? (
          <button
            type="button"
            onClick={onCancel}
            style={smallButton(theme.danger, theme.bg)}
          >
            Avbryt
          </button>
        ) : null}
        {done && onDismiss !== undefined ? (
          <button
            type="button"
            onClick={onDismiss}
            style={smallButton(theme.textMuted, theme.bg)}
          >
            Lukk
          </button>
        ) : null}
      </div>
      <ProgressBar {...(percent !== undefined ? { percent } : {})} />
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
        <SpeedReadout bytesPerSecond={progress?.bytesPerSecond ?? 0} />
        <ETAReadout {...(progress?.etaSeconds !== undefined ? { seconds: progress.etaSeconds } : { seconds: undefined })} />
      </div>
      {errorMessage !== null ? (
        <div style={{ fontSize: 12, color: theme.danger }}>{errorMessage}</div>
      ) : null}
    </div>
  );
}

function smallButton(fg: string, bg: string): React.CSSProperties {
  return {
    padding: '2px 8px',
    background: bg,
    color: fg,
    border: `1px solid ${fg}`,
    borderRadius: 4,
    fontSize: 11,
    cursor: 'pointer',
  };
}
