import { useEffect, useRef, useState } from 'react';
import { Linking, Pressable, Text, View } from 'react-native';
import { Download, FileIcon } from 'lucide-react-native';
import { toast } from 'sonner-native';
import type { Particle } from '@/api/types';
import { apiClient } from '@/api/client';
import { toUserMessage } from '@/lib/errors';

type FileParticle = Extract<Particle, { type: 'file' }>;

interface FileParticleViewProps {
  particle: FileParticle;
  paused: boolean;
  onEnded: () => void;
}

// Files don't auto-play; give the reader a beat to act before advancing.
const DWELL_DURATION_MS = 8000;

function formatBytes(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  const kb = bytes / 1024;
  if (kb < 1024) return `${kb.toFixed(0)} KB`;
  const mb = kb / 1024;
  if (mb < 1024) return `${mb.toFixed(1)} MB`;
  return `${(mb / 1024).toFixed(1)} GB`;
}

/**
 * File particle: name, size, and a download action. Tapping resolves a signed
 * URL and opens it (the OS handles the download / preview). Mirrors desktop's
 * file attachment, minus in-app preview.
 */
export function FileParticleView({
  particle,
  paused,
  onEnded,
}: FileParticleViewProps) {
  const { filename, size_bytes, object_id } = particle.properties;
  const [downloading, setDownloading] = useState(false);
  const elapsedRef = useRef(0);

  // Pause the dwell while a download is being resolved so the stream doesn't
  // advance out from under the user mid-tap.
  useEffect(() => {
    if (paused || downloading) return;
    const start = Date.now();
    const interval = setInterval(() => {
      elapsedRef.current += Date.now() - start;
      if (elapsedRef.current >= DWELL_DURATION_MS) {
        clearInterval(interval);
        onEnded();
      }
    }, 250);
    return () => clearInterval(interval);
  }, [paused, downloading, onEnded, particle.id]);

  const handleDownload = async () => {
    setDownloading(true);
    try {
      const url = await apiClient.getParticleDownloadUrl(object_id);
      const canOpen = await Linking.canOpenURL(url);
      if (!canOpen) throw new Error('Could not open this file.');
      await Linking.openURL(url);
    } catch (err) {
      toast.error(toUserMessage(err));
    } finally {
      setDownloading(false);
    }
  };

  return (
    <View className="flex-1 items-center justify-center px-8">
      <View className="bg-white/10 w-full max-w-sm rounded-2xl px-5 py-5">
        <View className="flex-row items-center gap-3">
          <FileIcon color="rgba(255,255,255,0.7)" size={26} strokeWidth={1.5} />
          <View className="flex-1">
            <Text
              className="text-white text-base font-semibold"
              numberOfLines={2}
            >
              {filename}
            </Text>
            <Text className="text-white/50 text-xs mt-0.5">
              {formatBytes(size_bytes)}
            </Text>
          </View>
        </View>

        <Pressable
          onPress={handleDownload}
          disabled={downloading}
          className="mt-5 flex-row items-center justify-center gap-2 rounded-xl bg-white py-3"
        >
          <Download color="#000000" size={16} strokeWidth={2} />
          <Text className="text-black text-base font-semibold">
            {downloading ? 'Opening…' : 'Download'}
          </Text>
        </Pressable>
      </View>
    </View>
  );
}
