'use client'

import { useState, useRef } from 'react'
import { trpc } from '@/lib/trpc/client'
import { toast } from 'sonner'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { Input } from '@/components/ui/input'
import {
  AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
  AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle,
  AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import { Eye, FileText, Upload, Download, Trash2, MessageSquare, X, Loader2 } from 'lucide-react'
import { formatDistanceToNow } from 'date-fns'
import { FilePreview, isOfficeFile } from '@/components/shared/file-viewer'

interface Props {
  /** Project the workspace belongs to — drives file list (project-scoped). */
  projectId: string
  /**
   * One MentorAssignment id on this project — needed only to mint upload tokens
   * (the token is signed against the assignment + project pair, but the file
   * itself is project-scoped so co-mentors see it).
   */
  mentorAssignmentId: string
  /** Set true on the applicant side to label uploads as "Team upload" — purely cosmetic. */
  asApplicant?: boolean
}

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

export function WorkspaceFilesPanel({ projectId, mentorAssignmentId, asApplicant }: Props) {
  const utils = trpc.useUtils()
  const inputRef = useRef<HTMLInputElement>(null)
  const [uploading, setUploading] = useState(false)
  const [description, setDescription] = useState('')

  const { data: files, isLoading } = trpc.mentor.workspaceGetFiles.useQuery(
    { projectId },
    { enabled: !!projectId }
  )

  const presign = trpc.mentor.workspaceGetUploadUrl.useMutation()
  const recordUpload = trpc.mentor.workspaceUploadFile.useMutation({
    onSuccess: () => {
      utils.mentor.workspaceGetFiles.invalidate({ projectId })
      setDescription('')
      toast.success('File uploaded')
    },
  })
  const downloadMutation = trpc.mentor.workspaceGetFileDownloadUrl.useMutation()
  const deleteMutation = trpc.mentor.workspaceDeleteFile.useMutation({
    onSuccess: () => {
      utils.mentor.workspaceGetFiles.invalidate({ projectId })
      toast.success('File deleted')
    },
    onError: (e) => toast.error(e.message),
  })

  const handleFileSelected = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return
    e.target.value = ''
    setUploading(true)
    try {
      const { uploadUrl, uploadToken } = await presign.mutateAsync({
        mentorAssignmentId,
        fileName: file.name,
        mimeType: file.type || 'application/octet-stream',
        size: file.size,
      })
      const putRes = await fetch(uploadUrl, {
        method: 'PUT',
        body: file,
        headers: { 'Content-Type': file.type || 'application/octet-stream' },
      })
      if (!putRes.ok) throw new Error(`Upload failed: HTTP ${putRes.status}`)
      await recordUpload.mutateAsync({ uploadToken, description: description || undefined })
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Upload failed')
    } finally {
      setUploading(false)
    }
  }

  const [previewFileId, setPreviewFileId] = useState<string | null>(null)
  const [previewUrl, setPreviewUrl] = useState<string | null>(null)
  const [previewLoading, setPreviewLoading] = useState(false)

  const canPreviewMime = (m: string, name: string) =>
    m.startsWith('video/') || m === 'application/pdf' || m.startsWith('image/') || isOfficeFile(m, name)

  const togglePreview = async (file: { id: string; mimeType: string; fileName: string }) => {
    if (previewFileId === file.id) {
      setPreviewFileId(null)
      setPreviewUrl(null)
      return
    }
    setPreviewFileId(file.id)
    setPreviewUrl(null)
    setPreviewLoading(true)
    try {
      const { url } = await downloadMutation.mutateAsync({ mentorFileId: file.id, disposition: 'inline' })
      setPreviewUrl(url)
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Preview failed')
      setPreviewFileId(null)
    } finally {
      setPreviewLoading(false)
    }
  }

  const handleDownload = async (mentorFileId: string) => {
    try {
      const { url } = await downloadMutation.mutateAsync({ mentorFileId, disposition: 'attachment' })
      const a = document.createElement('a')
      a.href = url
      a.download = ''
      a.rel = 'noopener'
      document.body.appendChild(a)
      a.click()
      a.remove()
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Download failed')
    }
  }

  if (isLoading) {
    return (
      <Card>
        <CardHeader><CardTitle>Workspace Files</CardTitle></CardHeader>
        <CardContent className="space-y-2">
          <Skeleton className="h-12 w-full" />
          <Skeleton className="h-12 w-full" />
        </CardContent>
      </Card>
    )
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>Workspace Files</CardTitle>
        <CardDescription>
          {asApplicant
            ? 'Files shared with your mentor in this workspace.'
            : 'Files you and the team have shared in this workspace.'}
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        <div className="flex flex-col sm:flex-row gap-2">
          <Input
            value={description}
            onChange={(e) => setDescription(e.target.value)}
            placeholder="Optional description for the next upload"
            className="flex-1"
          />
          <Button
            disabled={uploading}
            onClick={() => inputRef.current?.click()}
            className="shrink-0"
          >
            <Upload className="mr-2 h-4 w-4" />
            {uploading ? 'Uploading…' : 'Upload file'}
          </Button>
          <input ref={inputRef} type="file" hidden onChange={handleFileSelected} />
        </div>

        {files && files.length === 0 && (
          <div className="text-center py-8 text-sm text-muted-foreground">
            <FileText className="h-10 w-10 mx-auto mb-2 opacity-40" />
            No files in this workspace yet.
          </div>
        )}

        <ul className="divide-y">
          {(files ?? []).map((f) => {
            const isOpen = previewFileId === f.id
            const previewable = canPreviewMime(f.mimeType, f.fileName)
            return (
            <li key={f.id} className="py-3 space-y-2">
              <div className="flex items-center gap-3">
              <FileText className="h-5 w-5 text-muted-foreground shrink-0" />
              <div className="flex-1 min-w-0">
                <div className="font-medium truncate">{f.fileName}</div>
                <div className="text-xs text-muted-foreground">
                  {f.uploadedBy.name ?? f.uploadedBy.email} · {formatSize(f.size)} ·{' '}
                  {formatDistanceToNow(new Date(f.createdAt), { addSuffix: true })}
                  {f._count.comments > 0 && (
                    <span className="ml-2 inline-flex items-center gap-1">
                      <MessageSquare className="h-3 w-3" />
                      {f._count.comments}
                    </span>
                  )}
                </div>
                {f.description && (
                  <div className="text-xs text-muted-foreground mt-1">{f.description}</div>
                )}
              </div>
              {previewable && (
                <Button
                  variant="ghost"
                  size="icon"
                  onClick={() => togglePreview(f)}
                  title={isOpen ? 'Close preview' : 'Preview'}
                  aria-label={isOpen ? 'Close preview' : 'Preview file'}
                >
                  {isOpen ? <X className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
                </Button>
              )}
              <Button
                variant="ghost"
                size="icon"
                onClick={() => handleDownload(f.id)}
                title="Download"
                aria-label="Download file"
              >
                <Download className="h-4 w-4" />
              </Button>
              <AlertDialog>
                <AlertDialogTrigger asChild>
                  <Button variant="ghost" size="icon" className="text-destructive hover:text-destructive">
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </AlertDialogTrigger>
                <AlertDialogContent>
                  <AlertDialogHeader>
                    <AlertDialogTitle>Delete this file?</AlertDialogTitle>
                    <AlertDialogDescription>
                      This removes the file from MinIO and the workspace. Comments on the file are deleted with it.
                    </AlertDialogDescription>
                  </AlertDialogHeader>
                  <AlertDialogFooter>
                    <AlertDialogCancel>Cancel</AlertDialogCancel>
                    <AlertDialogAction onClick={() => deleteMutation.mutate({ mentorFileId: f.id })}>
                      Delete
                    </AlertDialogAction>
                  </AlertDialogFooter>
                </AlertDialogContent>
              </AlertDialog>
              </div>
              {isOpen && (
                <div className="rounded-md border bg-muted/30 overflow-hidden">
                  {previewLoading || !previewUrl ? (
                    <div className="flex items-center justify-center py-12 text-sm text-muted-foreground">
                      <Loader2 className="h-4 w-4 mr-2 animate-spin" />
                      Loading preview…
                    </div>
                  ) : (
                    <FilePreview file={{ mimeType: f.mimeType, fileName: f.fileName }} url={previewUrl} />
                  )}
                </div>
              )}
            </li>
            )
          })}
        </ul>
      </CardContent>
    </Card>
  )
}
