'use client'

import { useState } from 'react'
import { trpc } from '@/lib/trpc/client'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Skeleton } from '@/components/ui/skeleton'
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog'
import {
  FileText,
  Video,
  File,
  Download,
  ExternalLink,
  Play,
  FileImage,
  Loader2,
  AlertCircle,
  X,
  History,
  PackageOpen,
  CheckCircle2,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'

const OFFICE_MIME_TYPES = [
  'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',   // .docx
  'application/vnd.ms-powerpoint',  // .ppt
  'application/msword',             // .doc
]

const OFFICE_EXTENSIONS = ['.pptx', '.ppt', '.docx', '.doc']

export function isOfficeFile(mimeType: string, fileName: string): boolean {
  if (OFFICE_MIME_TYPES.includes(mimeType)) return true
  const ext = fileName.toLowerCase().slice(fileName.lastIndexOf('.'))
  return OFFICE_EXTENSIONS.includes(ext)
}

interface FileRequirementInfo {
  id: string
  name: string
  description?: string | null
  isRequired: boolean
}

interface ProjectFile {
  id: string
  fileType: 'EXEC_SUMMARY' | 'PRESENTATION' | 'VIDEO' | 'OTHER' | 'BUSINESS_PLAN' | 'VIDEO_PITCH' | 'SUPPORTING_DOC'
  fileName: string
  mimeType: string
  size: number
  bucket: string
  objectKey: string
  version?: number
  isLate?: boolean
  requirementId?: string | null
  requirement?: FileRequirementInfo | null
  // Document analysis fields
  pageCount?: number | null
  textPreview?: string | null
  detectedLang?: string | null
  langConfidence?: number | null
  analyzedAt?: Date | string | null
}

interface RoundGroup {
  roundId: string | null
  roundName: string
  sortOrder: number
  files: Array<ProjectFile & { isLate?: boolean }>
}

interface FileViewerProps {
  files?: ProjectFile[]
  groupedFiles?: RoundGroup[]
  projectId?: string
  roundId?: string
  className?: string
}

function formatFileSize(bytes: number): string {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

function getFileIcon(fileType: string, mimeType: string) {
  if (mimeType.startsWith('video/')) return Video
  if (mimeType.startsWith('image/')) return FileImage
  if (mimeType === 'application/pdf') return FileText
  if (fileType === 'EXEC_SUMMARY' || fileType === 'PRESENTATION') return FileText
  if (fileType === 'VIDEO') return Video
  return File
}

function getFileTypeLabel(fileType: string) {
  switch (fileType) {
    case 'EXEC_SUMMARY':
      return 'Executive Summary'
    case 'PRESENTATION':
      return 'Presentation'
    case 'VIDEO':
      return 'Video'
    case 'BUSINESS_PLAN':
      return 'Business Plan'
    case 'VIDEO_PITCH':
      return 'Video Pitch'
    case 'SUPPORTING_DOC':
      return 'Supporting Document'
    default:
      return 'Attachment'
  }
}

export function FileViewer({ files, groupedFiles, projectId, roundId, className }: FileViewerProps) {
  // Render grouped view if groupedFiles is provided
  if (groupedFiles) {
    return <GroupedFileViewer groupedFiles={groupedFiles} className={className} />
  }

  // Render flat view (backward compatible)
  if (!files || files.length === 0) {
    return (
      <Card className={className}>
        <CardContent className="flex flex-col items-center justify-center py-8 text-center">
          <File className="h-12 w-12 text-muted-foreground/50" />
          <p className="mt-2 font-medium">No files attached</p>
          <p className="text-sm text-muted-foreground">
            This project has no files uploaded yet
          </p>
        </CardContent>
      </Card>
    )
  }

  // Sort files by type order
  const typeSortOrder = ['EXEC_SUMMARY', 'BUSINESS_PLAN', 'PRESENTATION', 'VIDEO', 'VIDEO_PITCH', 'SUPPORTING_DOC', 'OTHER']
  const sortedFiles = [...files].sort(
    (a, b) => typeSortOrder.indexOf(a.fileType) - typeSortOrder.indexOf(b.fileType)
  )

  return (
    <div className={cn('space-y-4', className)}>
      {/* Requirement Fulfillment Checklist */}
      {roundId && <RequirementChecklist roundId={roundId} files={files} />}

      <Card>
      <CardHeader className="flex flex-row items-center justify-between space-y-0">
        <CardTitle className="text-lg">Project Files</CardTitle>
        {projectId && files.length > 1 && (
          <BulkDownloadButton projectId={projectId} fileIds={files.map((f) => f.id)} />
        )}
      </CardHeader>
      <CardContent className="space-y-3">
        {sortedFiles.map((file) => (
          <FileItem key={file.id} file={file} />
        ))}
      </CardContent>
      </Card>
    </div>
  )
}

function GroupedFileViewer({ groupedFiles, className }: { groupedFiles: RoundGroup[], className?: string }) {
  const hasAnyFiles = groupedFiles.some(group => group.files.length > 0)

  if (!hasAnyFiles) {
    return (
      <Card className={className}>
        <CardContent className="flex flex-col items-center justify-center py-8 text-center">
          <File className="h-12 w-12 text-muted-foreground/50" />
          <p className="mt-2 font-medium">No files attached</p>
          <p className="text-sm text-muted-foreground">
            This project has no files uploaded yet
          </p>
        </CardContent>
      </Card>
    )
  }

  // Sort groups by sortOrder
  const sortedGroups = [...groupedFiles].sort((a, b) => a.sortOrder - b.sortOrder)

  // Sort files within each group by type order
  const fileTypeSortOrder = ['EXEC_SUMMARY', 'BUSINESS_PLAN', 'PRESENTATION', 'VIDEO', 'VIDEO_PITCH', 'SUPPORTING_DOC', 'OTHER']

  return (
    <Card className={className}>
      <CardHeader>
        <CardTitle className="text-lg">Project Files</CardTitle>
      </CardHeader>
      <CardContent className="space-y-6">
        {sortedGroups.map((group) => {
          if (group.files.length === 0) return null

          const sortedFiles = [...group.files].sort(
            (a, b) => fileTypeSortOrder.indexOf(a.fileType) - fileTypeSortOrder.indexOf(b.fileType)
          )

          return (
            <div key={group.roundId || 'no-round'} className="space-y-3">
              {/* Round header */}
              <div className="flex items-center justify-between border-b pb-2">
                <h3 className="font-semibold text-sm text-muted-foreground uppercase tracking-wide">
                  {group.roundName}
                </h3>
                <Badge variant="outline" className="text-xs">
                  {group.files.length} {group.files.length === 1 ? 'file' : 'files'}
                </Badge>
              </div>

              {/* Files in this stage */}
              <div className="space-y-3">
                {sortedFiles.map((file) => (
                  <FileItem key={file.id} file={file} />
                ))}
              </div>
            </div>
          )
        })}
      </CardContent>
    </Card>
  )
}

function FileItem({ file }: { file: ProjectFile }) {
  const [showPreview, setShowPreview] = useState(false)
  const Icon = getFileIcon(file.fileType, file.mimeType)

  const { data: urlData, isLoading: isLoadingUrl } = trpc.file.getDownloadUrl.useQuery(
    { bucket: file.bucket, objectKey: file.objectKey, purpose: 'preview' as const },
    { enabled: showPreview }
  )

  const canPreview =
    file.mimeType.startsWith('video/') ||
    file.mimeType === 'application/pdf' ||
    file.mimeType.startsWith('image/') ||
    isOfficeFile(file.mimeType, file.fileName)

  return (
    <div className="space-y-2">
      <div className="rounded-lg border p-3">
        <div className="flex items-start gap-3">
          <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted">
            <Icon className="h-5 w-5 text-muted-foreground" />
          </div>

          <div className="flex-1 min-w-0">
            {file.requirement && (
              <p className="text-xs font-semibold text-primary/80 mb-0.5 uppercase tracking-wide">
                {file.requirement.name}
              </p>
            )}
            <div className="flex items-center gap-2">
              <p className="font-medium truncate">{file.fileName}</p>
              {file.version != null && file.version > 1 && (
                <Badge variant="outline" className="text-xs shrink-0">
                  v{file.version}
                </Badge>
              )}
            </div>
            <div className="flex items-center gap-2 text-sm text-muted-foreground flex-wrap">
              <Badge variant="secondary" className="text-xs">
                {getFileTypeLabel(file.fileType)}
              </Badge>
              {file.isLate && (
                <Badge variant="destructive" className="text-xs">
                  Late
                </Badge>
              )}
              <span>{formatFileSize(file.size)}</span>
              {file.pageCount != null && (
                <Badge variant="outline" className="text-xs gap-1">
                  <FileText className="h-3 w-3" />
                  {file.pageCount} {file.pageCount === 1 ? 'page' : 'pages'}
                </Badge>
              )}
              {file.detectedLang && file.detectedLang !== 'und' && (
                <Badge
                  variant="outline"
                  className={cn('text-xs font-mono uppercase', {
                    'border-green-300 text-green-700 bg-green-50': file.langConfidence != null && file.langConfidence >= 0.8,
                    'border-amber-300 text-amber-700 bg-amber-50': file.langConfidence != null && file.langConfidence >= 0.4 && file.langConfidence < 0.8,
                    'border-red-300 text-red-700 bg-red-50': file.langConfidence != null && file.langConfidence < 0.4,
                  })}
                  title={`Language: ${file.detectedLang} (${Math.round((file.langConfidence ?? 0) * 100)}% confidence)`}
                >
                  {file.detectedLang.toUpperCase()}
                </Badge>
              )}
            </div>
          </div>

          {/* Desktop action buttons — hidden on mobile */}
          <div className="hidden md:flex items-center gap-1 shrink-0">
            {file.version != null && file.version > 1 && (
              <VersionHistoryButton fileId={file.id} />
            )}
            {canPreview && (
              <Button
                variant="outline"
                size="sm"
                onClick={() => setShowPreview(!showPreview)}
              >
                {showPreview ? (
                  <>
                    <X className="mr-2 h-4 w-4" />
                    Close
                  </>
                ) : (
                  <>
                    <Play className="mr-2 h-4 w-4" />
                    Preview
                  </>
                )}
              </Button>
            )}
            <FileOpenButton file={file} />
            <FileDownloadButton file={file} />
          </div>
        </div>

        {/* Mobile action button — open in new tab only (download unreliable on iOS) */}
        <div className="flex md:hidden items-center gap-2 mt-3 pt-3 border-t">
          <FileOpenButton file={file} className="flex-1" label="Open in New Tab" />
        </div>
      </div>

      {/* Preview area — desktop only */}
      {showPreview && (
        <div className="hidden md:block rounded-lg border bg-muted/50 overflow-hidden">
          {isLoadingUrl ? (
            <div className="flex items-center justify-center py-8">
              <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
            </div>
          ) : urlData?.url ? (
            <FilePreview file={file} url={urlData.url} />
          ) : (
            <div className="flex items-center justify-center py-8 text-muted-foreground">
              <AlertCircle className="mr-2 h-4 w-4" />
              Failed to load preview
            </div>
          )}
        </div>
      )}
    </div>
  )
}

function VersionHistoryButton({ fileId }: { fileId: string }) {
  const [open, setOpen] = useState(false)

  const { data: versions, isLoading } = trpc.file.getVersionHistory.useQuery(
    { fileId },
    { enabled: open }
  )

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button variant="ghost" size="sm" title="Version history">
          <History className="h-4 w-4" />
        </Button>
      </DialogTrigger>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>Version History</DialogTitle>
        </DialogHeader>
        <div className="space-y-2 max-h-[60vh] overflow-y-auto">
          {isLoading ? (
            <div className="space-y-2">
              {[1, 2, 3].map((i) => (
                <Skeleton key={i} className="h-14 w-full" />
              ))}
            </div>
          ) : versions && (versions as Array<Record<string, unknown>>).length > 0 ? (
            (versions as Array<Record<string, unknown>>).map((v) => (
              <div
                key={String(v.id)}
                className={cn(
                  'flex items-center gap-3 rounded-lg border p-3',
                  String(v.id) === fileId && 'border-primary bg-primary/5'
                )}
              >
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <p className="text-sm font-medium truncate">
                      {String(v.fileName)}
                    </p>
                    <Badge variant={String(v.id) === fileId ? 'default' : 'outline'} className="text-xs shrink-0">
                      v{String(v.version)}
                    </Badge>
                  </div>
                  <div className="flex items-center gap-2 text-xs text-muted-foreground">
                    <span>{formatFileSize(Number(v.size))}</span>
                    <span>
                      {v.createdAt
                        ? new Date(String(v.createdAt)).toLocaleDateString(undefined, {
                            year: 'numeric',
                            month: 'short',
                            day: 'numeric',
                            hour: '2-digit',
                            minute: '2-digit',
                          })
                        : ''}
                    </span>
                  </div>
                </div>
                <VersionDownloadButton
                  bucket={String(v.bucket)}
                  objectKey={String(v.objectKey)}
                />
              </div>
            ))
          ) : (
            <p className="text-sm text-muted-foreground text-center py-4">
              No version history available
            </p>
          )}
        </div>
      </DialogContent>
    </Dialog>
  )
}

function VersionDownloadButton({ bucket, objectKey }: { bucket: string; objectKey: string }) {
  const [downloading, setDownloading] = useState(false)

  const { refetch } = trpc.file.getDownloadUrl.useQuery(
    { bucket, objectKey, purpose: 'open' as const },
    { enabled: false }
  )

  const handleDownload = async () => {
    setDownloading(true)
    try {
      const result = await refetch()
      if (result.data?.url) {
        window.open(result.data.url, '_blank')
      }
    } catch {
      toast.error('Failed to get download URL')
    } finally {
      setDownloading(false)
    }
  }

  return (
    <Button
      variant="ghost"
      size="icon"
      className="h-8 w-8 shrink-0"
      onClick={handleDownload}
      disabled={downloading}
      aria-label="Download this version"
    >
      {downloading ? (
        <Loader2 className="h-4 w-4 animate-spin" />
      ) : (
        <Download className="h-4 w-4" />
      )}
    </Button>
  )
}

function BulkDownloadButton({ projectId, fileIds }: { projectId: string; fileIds: string[] }) {
  const [downloading, setDownloading] = useState(false)

  const { refetch } = trpc.file.getBulkDownloadUrls.useQuery(
    { projectId, fileIds },
    { enabled: false }
  )

  const handleBulkDownload = async () => {
    setDownloading(true)
    try {
      const result = await refetch()
      if (result.data && Array.isArray(result.data)) {
        // Each URL already has Content-Disposition: attachment from the server,
        // so we can trigger native downloads by navigating to each URL.
        // Use hidden iframes to download multiple files without navigating away.
        for (let i = 0; i < result.data.length; i++) {
          const item = result.data[i] as { downloadUrl: string; fileName?: string }
          if (item.downloadUrl) {
            const iframe = document.createElement('iframe')
            iframe.style.display = 'none'
            iframe.src = item.downloadUrl
            document.body.appendChild(iframe)
            // Clean up iframe after download starts
            setTimeout(() => document.body.removeChild(iframe), 10_000)
            // Small delay between downloads to avoid browser throttling
            if (i < result.data.length - 1) {
              await new Promise((resolve) => setTimeout(resolve, 800))
            }
          }
        }
        toast.success(`Downloading ${result.data.length} files`)
      }
    } catch {
      toast.error('Failed to download files')
    } finally {
      setTimeout(() => setDownloading(false), 1000)
    }
  }

  return (
    <Button
      variant="outline"
      size="sm"
      onClick={handleBulkDownload}
      disabled={downloading}
    >
      {downloading ? (
        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
      ) : (
        <PackageOpen className="mr-2 h-4 w-4" />
      )}
      Download All
    </Button>
  )
}

function FileOpenButton({ file, className, label }: { file: ProjectFile; className?: string; label?: string }) {
  const [loading, setLoading] = useState(false)

  const { refetch } = trpc.file.getDownloadUrl.useQuery(
    { bucket: file.bucket, objectKey: file.objectKey, purpose: 'open' as const },
    { enabled: false }
  )

  const handleOpen = async () => {
    setLoading(true)
    // Open the blank window immediately in the click handler (synchronous)
    // so iOS Safari doesn't block it as a popup
    const newWindow = window.open('about:blank', '_blank')
    try {
      const result = await refetch()
      if (result.data?.url) {
        if (newWindow) {
          newWindow.location.href = result.data.url
        } else {
          // Fallback: if popup was still blocked, navigate current tab
          window.location.href = result.data.url
        }
      } else {
        newWindow?.close()
      }
    } catch (error) {
      console.error('Failed to get URL:', error)
      newWindow?.close()
      toast.error('Failed to open file')
    } finally {
      setLoading(false)
    }
  }

  return (
    <Button
      variant="outline"
      size="sm"
      onClick={handleOpen}
      disabled={loading}
      aria-label="Open file in new tab"
      className={className}
    >
      {loading ? (
        <Loader2 className={cn('h-4 w-4 animate-spin', label && 'mr-1.5')} />
      ) : (
        <ExternalLink className={cn('h-4 w-4', label && 'mr-1.5')} />
      )}
      {label}
    </Button>
  )
}

function FileDownloadButton({ file, className, label }: { file: ProjectFile; className?: string; label?: string }) {
  const [downloading, setDownloading] = useState(false)

  const { refetch } = trpc.file.getDownloadUrl.useQuery(
    { bucket: file.bucket, objectKey: file.objectKey, forDownload: true, fileName: file.fileName, purpose: 'download' as const },
    { enabled: false }
  )

  const handleDownload = async () => {
    setDownloading(true)
    try {
      const result = await refetch()
      if (result.data?.url) {
        // The presigned URL includes Content-Disposition: attachment header,
        // so the browser will natively download the file (works on iOS Safari too).
        // Use window.location.href for same-tab navigation which triggers download
        // without popup blockers interfering.
        window.location.href = result.data.url
      }
    } catch (error) {
      console.error('Failed to download file:', error)
      toast.error('Failed to download file')
    } finally {
      // Small delay before clearing state so the button doesn't flash
      setTimeout(() => setDownloading(false), 1000)
    }
  }

  return (
    <Button
      variant="outline"
      size="sm"
      onClick={handleDownload}
      disabled={downloading}
      aria-label="Download file"
      className={className}
    >
      {downloading ? (
        <Loader2 className={cn('h-4 w-4 animate-spin', label && 'mr-1.5')} />
      ) : (
        <Download className={cn('h-4 w-4', label && 'mr-1.5')} />
      )}
      {label}
    </Button>
  )
}

export function FilePreview({ file, url }: { file: { mimeType: string; fileName: string }; url: string }) {
  if (file.mimeType.startsWith('video/')) {
    return (
      <video
        src={url}
        controls
        className="w-full max-h-[500px]"
        preload="metadata"
      >
        Your browser does not support the video tag.
      </video>
    )
  }

  if (file.mimeType === 'application/pdf') {
    return (
      <div className="relative">
        <iframe
          src={`${url}#toolbar=0`}
          className="w-full h-[600px]"
          title={file.fileName}
        />
        <Button
          variant="secondary"
          size="sm"
          className="absolute top-2 right-2"
          asChild
        >
          <a href={url} target="_blank" rel="noopener noreferrer">
            <ExternalLink className="mr-2 h-4 w-4" />
            Open in new tab
          </a>
        </Button>
      </div>
    )
  }

  if (file.mimeType.startsWith('image/')) {
    return (
      <div className="relative flex items-center justify-center p-4">
        <img
          src={url}
          alt={file.fileName}
          className="max-w-full max-h-[500px] object-contain rounded-md"
        />
        <Button
          variant="secondary"
          size="sm"
          className="absolute top-2 right-2"
          asChild
        >
          <a href={url} target="_blank" rel="noopener noreferrer">
            <ExternalLink className="mr-2 h-4 w-4" />
            Open in new tab
          </a>
        </Button>
      </div>
    )
  }

  // Office documents (PPTX, DOCX, PPT, DOC)
  if (isOfficeFile(file.mimeType, file.fileName)) {
    const viewerUrl = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(url)}`
    return (
      <div className="relative">
        <iframe
          src={viewerUrl}
          className="w-full h-[600px]"
          title={file.fileName}
        />
        <Button
          variant="secondary"
          size="sm"
          className="absolute top-2 right-2"
          asChild
        >
          <a href={url} target="_blank" rel="noopener noreferrer">
            <ExternalLink className="mr-2 h-4 w-4" />
            Open in new tab
          </a>
        </Button>
      </div>
    )
  }

  return (
    <div className="flex items-center justify-center py-8 text-muted-foreground">
      Preview not available for this file type
    </div>
  )
}

// Compact file list for smaller views
export function FileList({ files, className }: FileViewerProps) {
  if (!files || files.length === 0) return null

  return (
    <div className={cn('space-y-2', className)}>
      {files.map((file) => {
        const Icon = getFileIcon(file.fileType, file.mimeType)
        return (
          <CompactFileItem key={file.id} file={file} />
        )
      })}
    </div>
  )
}

function CompactFileItem({ file }: { file: ProjectFile }) {
  const [loading, setLoading] = useState(false)
  const Icon = getFileIcon(file.fileType, file.mimeType)

  const { refetch } = trpc.file.getDownloadUrl.useQuery(
    { bucket: file.bucket, objectKey: file.objectKey, purpose: 'open' as const },
    { enabled: false }
  )

  const handleClick = async () => {
    setLoading(true)
    try {
      const result = await refetch()
      if (result.data?.url) {
        window.open(result.data.url, '_blank')
      }
    } catch (error) {
      console.error('Failed to get download URL:', error)
    } finally {
      setLoading(false)
    }
  }

  return (
    <button
      onClick={handleClick}
      disabled={loading}
      className="flex w-full items-center gap-2 rounded-md border p-2 text-left hover:bg-muted transition-colors disabled:opacity-50"
    >
      {loading ? (
        <Loader2 className="h-4 w-4 animate-spin shrink-0" />
      ) : (
        <Icon className="h-4 w-4 shrink-0 text-muted-foreground" />
      )}
      <span className="flex-1 truncate text-sm">{file.fileName}</span>
      {file.version != null && file.version > 1 && (
        <Badge variant="outline" className="text-xs shrink-0">
          v{file.version}
        </Badge>
      )}
      <span className="text-xs text-muted-foreground shrink-0">
        {formatFileSize(file.size)}
      </span>
    </button>
  )
}

/**
 * Displays a checklist of file requirements and their fulfillment status.
 * Used by admins/jury to see which required files have been uploaded.
 */
function RequirementChecklist({ roundId, files }: { roundId: string; files: ProjectFile[] }) {
  const { data: requirements = [] } = trpc.file.listRequirements.useQuery({ roundId })

  if (requirements.length === 0) return null

  const fulfilled = requirements.filter((req) =>
    files.some((f) => f.requirementId === req.id)
  ).length
  const total = requirements.length
  const allRequired = requirements.filter((r) => r.isRequired)
  const requiredFulfilled = allRequired.filter((req) =>
    files.some((f) => f.requirementId === req.id)
  ).length

  return (
    <Card>
      <CardHeader className="pb-3">
        <div className="flex items-center justify-between">
          <CardTitle className="text-lg">Document Requirements</CardTitle>
          <Badge variant={requiredFulfilled === allRequired.length ? 'default' : 'destructive'}>
            {fulfilled}/{total} uploaded
          </Badge>
        </div>
      </CardHeader>
      <CardContent className="space-y-2">
        {requirements.map((req) => {
          const file = files.find((f) => f.requirementId === req.id)
          const isFulfilled = !!file

          return (
            <div
              key={req.id}
              className={cn(
                'flex items-center gap-3 rounded-lg border p-2.5 text-sm',
                isFulfilled
                  ? 'border-green-200 bg-green-50'
                  : req.isRequired
                    ? 'border-red-200 bg-red-50'
                    : 'border-muted'
              )}
            >
              {isFulfilled ? (
                <CheckCircle2 className="h-4 w-4 text-green-600 shrink-0" />
              ) : req.isRequired ? (
                <AlertCircle className="h-4 w-4 text-red-500 shrink-0" />
              ) : (
                <File className="h-4 w-4 text-muted-foreground shrink-0" />
              )}
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2">
                  <span className="font-medium">{req.name}</span>
                  <Badge
                    variant={req.isRequired ? 'destructive' : 'secondary'}
                    className="text-xs"
                  >
                    {req.isRequired ? 'Required' : 'Optional'}
                  </Badge>
                </div>
                {isFulfilled && file ? (
                  <p className="text-xs text-muted-foreground truncate">
                    {file.fileName} ({formatFileSize(file.size)})
                  </p>
                ) : (
                  <p className="text-xs text-muted-foreground">Not uploaded</p>
                )}
              </div>
              {isFulfilled && file && (
                <FileDownloadButton file={file} />
              )}
            </div>
          )
        })}
      </CardContent>
    </Card>
  )
}

export function FileViewerSkeleton() {
  return (
    <Card>
      <CardHeader>
        <Skeleton className="h-5 w-28" />
      </CardHeader>
      <CardContent className="space-y-3">
        {[1, 2, 3].map((i) => (
          <div key={i} className="flex items-center gap-3 rounded-lg border p-3">
            <Skeleton className="h-10 w-10 rounded-lg" />
            <div className="flex-1 space-y-2">
              <Skeleton className="h-4 w-48" />
              <Skeleton className="h-3 w-24" />
            </div>
            <Skeleton className="h-9 w-20" />
          </div>
        ))}
      </CardContent>
    </Card>
  )
}
