"use client"

import { useTranslations } from "next-intl"
import { Download, ZoomIn, ZoomOut, FileText } from "lucide-react"

import { Button } from "@/shared/components/ui/button"
import { FileIcon } from "./file-icon"
import { formatFileSize } from "@/shared/lib/file-storage"
import { useFilePreview, useImageZoom } from "../hooks/use-file-preview"
import type { FileAttachment } from "../types"

interface FilePreviewProps {
  file: FileAttachment
  className?: string
}

type PreviewKind = "image" | "pdf" | "text" | "office" | "other"

const TEXT_MIME_TYPES = new Set([
  "text/plain",
  "text/markdown",
  "text/csv",
  "application/json",
  "text/html",
  "text/css",
  "text/javascript",
])

const OFFICE_MIME_TYPES = new Set([
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "application/vnd.ms-powerpoint",
  "application/vnd.openxmlformats-officedocument.presentationml.presentation",
])

function classify(mimeType: string): PreviewKind {
  if (mimeType.startsWith("image/")) return "image"
  if (mimeType === "application/pdf") return "pdf"
  if (TEXT_MIME_TYPES.has(mimeType)) return "text"
  if (OFFICE_MIME_TYPES.has(mimeType)) return "office"
  return "other"
}

export function FilePreview({ file, className }: FilePreviewProps): React.ReactElement {
  const t = useTranslations("files.preview")
  const kind = classify(file.mimeType)
  const url = file.url ?? "#"

  return (
    <div className={className}>
      <div className="mb-3 flex items-center justify-between gap-3">
        <div className="flex min-w-0 items-center gap-2">
          <FileIcon mimeType={file.mimeType} className="h-5 w-5" />
          <div className="min-w-0">
            <p className="truncate text-sm font-medium" title={file.originalName}>
              {file.originalName}
            </p>
            <p className="text-xs text-muted-foreground">
              {formatFileSize(file.size)} · {file.mimeType}
            </p>
          </div>
        </div>
        <Button asChild variant="outline" size="sm">
          <a
            href={url}
            download={file.originalName}
            target="_blank"
            rel="noopener noreferrer"
            aria-label={`${t("download")} ${file.originalName}`}
          >
            <Download className="mr-2 h-4 w-4" aria-hidden="true" />
            {t("download")}
          </a>
        </Button>
      </div>

      <PreviewBody kind={kind} file={file} url={url} />
    </div>
  )
}

function PreviewBody({
  kind,
  file,
  url,
}: {
  kind: PreviewKind
  file: FileAttachment
  url: string
}): React.ReactElement {
  if (kind === "image") {
    return <ImagePreview url={url} alt={file.originalName} />
  }

  if (kind === "pdf") {
    return (
      <iframe
        src={url}
        title={file.originalName}
        aria-label={`PDF preview: ${file.originalName}`}
        className="h-[70vh] w-full rounded-md border"
      />
    )
  }

  if (kind === "text") {
    return <TextPreview url={url} />
  }

  return <OtherPreview kind={kind} file={file} url={url} />
}

function ImagePreview({ url, alt }: { url: string; alt: string }): React.ReactElement {
  const t = useTranslations("files.preview")
  const { zoom, zoomIn, zoomOut, canZoomIn, canZoomOut } = useImageZoom()

  return (
    <div className="space-y-2">
      <div className="flex items-center justify-end gap-2">
        <Button
          type="button"
          variant="outline"
          size="icon"
          className="h-8 w-8"
          onClick={zoomOut}
          disabled={!canZoomOut}
          aria-label={t("zoomOut")}
        >
          <ZoomOut className="h-4 w-4" aria-hidden="true" />
        </Button>
        <span className="w-12 text-center text-xs text-muted-foreground" aria-live="polite">
          {Math.round(zoom * 100)}%
        </span>
        <Button
          type="button"
          variant="outline"
          size="icon"
          className="h-8 w-8"
          onClick={zoomIn}
          disabled={!canZoomIn}
          aria-label={t("zoomIn")}
        >
          <ZoomIn className="h-4 w-4" aria-hidden="true" />
        </Button>
      </div>
      <div
        className="overflow-auto rounded-md border bg-muted/30 p-2"
        style={{ maxHeight: "70vh" }}
      >
        {/* eslint-disable-next-line @next/next/no-img-element */}
        <img
          src={url}
          alt={alt}
          style={{ transform: `scale(${zoom})`, transformOrigin: "top left" }}
          className="mx-auto max-w-full transition-transform"
        />
      </div>
    </div>
  )
}

function TextPreview({ url }: { url: string }): React.ReactElement {
  const t = useTranslations("files.preview.text")
  const { content, error, loading, load } = useFilePreview()

  if (content === null && !error && !loading) {
    return (
      <div className="flex flex-col items-center justify-center rounded-md border border-dashed p-12 text-center">
        <FileText className="h-12 w-12 text-muted-foreground" aria-hidden="true" />
        <p className="mt-3 text-sm font-medium">{t("title")}</p>
        <p className="mt-1 text-xs text-muted-foreground">{t("hint")}</p>
        <Button
          variant="outline"
          size="sm"
          className="mt-4"
          onClick={() => void load(url)}
        >
          {t("load")}
        </Button>
      </div>
    )
  }

  if (loading) {
    return (
      <div
        role="status"
        className="rounded-md border bg-muted/30 p-12 text-center text-sm text-muted-foreground"
      >
        {t("loading")}
      </div>
    )
  }

  if (error) {
    return (
      <div
        role="alert"
        className="flex flex-col items-center justify-center gap-3 rounded-md border border-destructive/40 bg-destructive/10 p-4 text-sm text-destructive"
      >
        <span>{t("error", { message: error })}</span>
        <Button
          variant="outline"
          size="sm"
          onClick={() => void load(url)}
        >
          {t("load")}
        </Button>
      </div>
    )
  }

  return (
    <pre className="max-h-[70vh] overflow-auto rounded-md border bg-background p-4 text-xs leading-relaxed">
      <code>{content}</code>
    </pre>
  )
}

function OtherPreview({
  kind,
  file,
  url,
}: {
  kind: PreviewKind
  file: FileAttachment
  url: string
}): React.ReactElement {
  const t = useTranslations("files.preview")
  const isOffice = kind === "office"
  const title = isOffice ? t("office.title") : t("other.title")
  const hint = isOffice ? t("office.hint") : t("other.hint")

  return (
    <div className="flex flex-col items-center justify-center rounded-md border border-dashed p-12 text-center">
      <FileIcon mimeType={file.mimeType} className="h-12 w-12" />
      <p className="mt-3 text-sm font-medium">{title}</p>
      <p className="mt-1 text-xs text-muted-foreground">{hint}</p>
      <Button asChild variant="outline" size="sm" className="mt-4">
        <a
          href={url}
          download={file.originalName}
          target="_blank"
          rel="noopener noreferrer"
          aria-label={`${t("download")} ${file.originalName}`}
        >
          <Download className="mr-2 h-4 w-4" aria-hidden="true" />
          {t("download")}
        </a>
      </Button>
    </div>
  )
}
