'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,
} 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']

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 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
}

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

interface FileViewerProps {
  files?: ProjectFile[]
  groupedFiles?: RoundGroup[]
  projectId?: 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, 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 sortOrder = ['EXEC_SUMMARY', 'BUSINESS_PLAN', 'PRESENTATION', 'VIDEO', 'VIDEO_PITCH', 'SUPPORTING_DOC', 'OTHER']
  const sortedFiles = [...files].sort(
    (a, b) => sortOrder.indexOf(a.fileType) - sortOrder.indexOf(b.fileType)
  )

  return (
    <Card className={className}>
      <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>
  )
}

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 round */}
              <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 },
    { 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="flex items-center gap-3 rounded-lg border p-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">
          <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>
          </div>
        </div>

        <div className="flex items-center gap-1">
          {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>

      {/* Preview area */}
      {showPreview && (
        <div className="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 },
    { 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)) {
        // Open each download URL with a small delay to avoid popup blocking
        for (let i = 0; i < result.data.length; i++) {
          const item = result.data[i] as { downloadUrl: string }
          if (item.downloadUrl) {
            // Use link element to trigger download without popup
            const link = document.createElement('a')
            link.href = item.downloadUrl
            link.target = '_blank'
            link.rel = 'noopener noreferrer'
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link)
            // Small delay between downloads
            if (i < result.data.length - 1) {
              await new Promise((resolve) => setTimeout(resolve, 300))
            }
          }
        }
        toast.success(`Downloading ${result.data.length} files`)
      }
    } catch {
      toast.error('Failed to download files')
    } finally {
      setDownloading(false)
    }
  }

  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 }: { file: ProjectFile }) {
  const [loading, setLoading] = useState(false)

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

  const handleOpen = 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 URL:', error)
    } finally {
      setLoading(false)
    }
  }

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

function FileDownloadButton({ file }: { file: ProjectFile }) {
  const [downloading, setDownloading] = useState(false)

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

  const handleDownload = async () => {
    setDownloading(true)
    try {
      const result = await refetch()
      if (result.data?.url) {
        // Force browser download via <a download>
        const link = document.createElement('a')
        link.href = result.data.url
        link.download = file.fileName
        link.rel = 'noopener noreferrer'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      }
    } catch (error) {
      console.error('Failed to get download URL:', error)
    } finally {
      setDownloading(false)
    }
  }

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

function FilePreview({ file, url }: { file: ProjectFile; 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 },
    { 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>
  )
}

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>
  )
}
