"use client"

import Link from "next/link"
import { useEffect, useMemo, useRef, useState } from "react"
import { useLocale, useTranslations } from "next-intl"
import { useParams, useSearchParams } from "next/navigation"

import {
  ArrowLeft,
  Loader2,
  RefreshCw,
  Send,
  Paperclip,
  LifeBuoy,
  ExternalLink,
  FileText,
  FileImage,
  FileVideo2,
  FileAudio2,
  File,
  ShieldAlert,
  CheckCircle2,
} from "lucide-react"

import {
  getSupportTicket,
  listTicketMessages,
  addTicketMessage,
  patchTicket,
  type SupportTicket,
  type TicketMessage,
} from "@/src/lib/api/customer-portal-support"

function cx(...c: Array<string | false | null | undefined>) {
  return c.filter(Boolean).join(" ")
}

function fmtTime(s?: string) {
  if (!s) return "—"
  const d = new Date(s)
  if (Number.isNaN(d.getTime())) return s
  return d.toLocaleString()
}

function bytesToHuman(n?: number | null) {
  const v = typeof n === "number" ? n : 0
  if (!v) return ""
  const units = ["B", "KB", "MB", "GB", "TB"]
  let x = v
  let i = 0
  while (x >= 1024 && i < units.length - 1) {
    x = x / 1024
    i++
  }
  return `${x.toFixed(i === 0 ? 0 : 1)} ${units[i]}`
}

/** Upload rules */
const MAX_FILE_MB = 10
const MAX_TOTAL_MB = 20
const MAX_FILE_BYTES = MAX_FILE_MB * 1024 * 1024
const MAX_TOTAL_BYTES = MAX_TOTAL_MB * 1024 * 1024

const ALLOWED_EXT = new Set([
  ".pdf",
  ".png", ".jpg", ".jpeg", ".webp", ".gif",
  ".doc", ".docx",
  ".xls", ".xlsx",
  ".ppt", ".pptx",
  ".txt", ".csv",
])

function getExt(name: string) {
  const n = (name || "").trim().toLowerCase()
  const i = n.lastIndexOf(".")
  return i >= 0 ? n.slice(i) : ""
}

function validateFilesFront(files: File[]) {
  let total = 0
  for (const f of files) {
    const ext = getExt(f.name)
    total += f.size

    if (!ALLOWED_EXT.has(ext)) return `File type not allowed: ${f.name}`
    if (f.size <= 0) return `Empty file is not allowed: ${f.name}`
    if (f.size > MAX_FILE_BYTES) return `File too large: ${f.name} (max ${MAX_FILE_MB} MB)`
    if (total > MAX_TOTAL_BYTES) return `Total upload too large (max ${MAX_TOTAL_MB} MB)`

    const lower = f.name.toLowerCase()
    if (lower.endsWith(".svg") || lower.endsWith(".zip") || lower.endsWith(".rar") || lower.endsWith(".7z")) {
      return `File type not allowed: ${f.name}`
    }
  }
  return null
}

const FILE_ACCEPT =
  ".pdf,.png,.jpg,.jpeg,.webp,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.csv"

function statusTone(status: string) {
  switch (status) {
    case "open":
      return { bg: "rgba(16,185,129,0.10)", bd: "rgba(16,185,129,0.25)", tx: "#047857" }
    case "in_progress":
      return { bg: "rgba(59,130,246,0.10)", bd: "rgba(59,130,246,0.25)", tx: "#1d4ed8" }
    case "waiting_customer":
      return { bg: "rgba(245,158,11,0.12)", bd: "rgba(245,158,11,0.28)", tx: "#92400e" }
    case "resolved":
      return { bg: "rgba(100,116,139,0.10)", bd: "rgba(100,116,139,0.22)", tx: "#334155" }
    case "closed":
      return { bg: "rgba(148,163,184,0.10)", bd: "rgba(148,163,184,0.25)", tx: "#475569" }
    default:
      return { bg: "rgba(15,23,42,0.06)", bd: "rgba(15,23,42,0.12)", tx: "#334155" }
  }
}

function priorityTone(priority: string) {
  return priority === "urgent"
    ? { bg: "rgba(239,68,68,0.10)", bd: "rgba(239,68,68,0.25)", tx: "#b91c1c" }
    : { bg: "rgba(16,185,129,0.08)", bd: "rgba(16,185,129,0.22)", tx: "#047857" }
}

function Badge({ label, tone }: { label: string; tone: { bg: string; bd: string; tx: string } }) {
  return (
    <span
      className="inline-flex items-center rounded-full border px-2 py-0.5 text-[11px] font-medium"
      style={{ background: tone.bg, borderColor: tone.bd, color: tone.tx }}
    >
      {label}
    </span>
  )
}

/** ---- PDF thumb (professional crop, no squeeze) ---- */
function PdfThumb({ url, title }: { url: string; title?: string }) {
  const canvasRef = useRef<HTMLCanvasElement | null>(null)
  const [state, setState] = useState<"idle" | "ok" | "fail">("idle")

  useEffect(() => {
    let canceled = false

    async function renderWithUrl(pdfjs: any, pdfUrl: string) {
      const task = pdfjs.getDocument({ url: pdfUrl })
      const pdf = await task.promise
      const page = await pdf.getPage(1)

      const viewport = page.getViewport({ scale: 1.0 })
      const targetW = 900
      const scale = Math.max(1.0, Math.min(targetW / viewport.width, 2.0))
      const vp = page.getViewport({ scale })

      const canvas = canvasRef.current
      if (!canvas) return
      const ctx = canvas.getContext("2d")
      if (!ctx) return

      canvas.width = Math.floor(vp.width)
      canvas.height = Math.floor(vp.height)

      await page.render({ canvasContext: ctx, viewport: vp }).promise
    }

    async function renderWithData(pdfjs: any, data: ArrayBuffer) {
      const task = pdfjs.getDocument({ data })
      const pdf = await task.promise
      const page = await pdf.getPage(1)

      const viewport = page.getViewport({ scale: 1.0 })
      const targetW = 900
      const scale = Math.max(1.0, Math.min(targetW / viewport.width, 2.0))
      const vp = page.getViewport({ scale })

      const canvas = canvasRef.current
      if (!canvas) return
      const ctx = canvas.getContext("2d")
      if (!ctx) return

      canvas.width = Math.floor(vp.width)
      canvas.height = Math.floor(vp.height)

      await page.render({ canvasContext: ctx, viewport: vp }).promise
    }

    async function fetchPdf(pdfUrl: string) {
      const token = typeof window !== "undefined" ? (localStorage.getItem("acx_cp_access") || "") : ""
      const res = await fetch(pdfUrl, {
        method: "GET",
        headers: token ? { Authorization: `Bearer ${token}` } : undefined,
      })
      if (!res.ok) throw new Error(`PDF fetch failed: ${res.status}`)
      return await res.arrayBuffer()
    }

    async function run() {
      try {
        setState("idle")
        const pdfjs: any = await import("pdfjs-dist")
        try {
          pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs"
        } catch {}

        try {
          await renderWithUrl(pdfjs, url)
          if (!canceled) setState("ok")
        } catch {
          const buf = await fetchPdf(url)
          await renderWithData(pdfjs, buf)
          if (!canceled) setState("ok")
        }
      } catch {
        if (!canceled) setState("fail")
      }
    }

    run()
    return () => {
      canceled = true
    }
  }, [url])

  function open() {
    if (!url) return
    window.open(url, "_blank", "noopener,noreferrer")
  }

  return (
    <div className="relative rounded-xl border overflow-hidden bg-white" style={{ borderColor: "rgba(0,0,0,0.10)" }}>
      <div
        className="relative w-full cursor-pointer"
        style={{ height: 180, overflow: "hidden", background: "linear-gradient(180deg, rgba(0,0,0,0.02), rgba(0,0,0,0.00))" }}
        onClick={open}
        role="button"
        title={title || "PDF"}
      >
        <canvas
          ref={canvasRef}
          className="block w-full"
          style={{
            height: "auto",
            transform: "scale(0.86)",
            transformOrigin: "top center",
          }}
        />

        <div className="absolute inset-x-0 bottom-0 h-10"
             style={{ background: "linear-gradient(180deg, rgba(255,255,255,0), rgba(255,255,255,1))" }} />

        <div className="absolute left-3 top-3 inline-flex items-center gap-2 rounded-full border bg-white/90 px-2.5 py-1 text-[11px]"
             style={{ borderColor: "rgba(16,185,129,0.25)" }}>
          <FileText className="h-3.5 w-3.5 text-emerald-700" />
          <span className="font-medium text-emerald-800">PDF</span>
          <span className="text-neutral-500">• Page 1</span>
        </div>

        <div className="absolute right-3 top-3 inline-flex items-center gap-1 rounded-full bg-emerald-600 px-2.5 py-1 text-[11px] text-white shadow-sm">
          <ExternalLink className="h-3.5 w-3.5" />
          Open
        </div>

        {state === "idle" ? (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="inline-flex items-center gap-2 rounded-full border bg-white px-3 py-1.5 text-xs text-neutral-600"
                 style={{ borderColor: "rgba(0,0,0,0.12)" }}>
              <Loader2 className="h-4 w-4 animate-spin" />
              Preparing preview…
            </div>
          </div>
        ) : null}

        {state === "fail" ? (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="rounded-xl border bg-white px-3 py-2 text-xs text-neutral-600"
                 style={{ borderColor: "rgba(0,0,0,0.12)" }}>
              Preview unavailable — click to open.
            </div>
          </div>
        ) : null}
      </div>

      <div className="px-3 py-2 border-t text-xs text-neutral-600" style={{ borderColor: "rgba(0,0,0,0.08)" }}>
        <div className="truncate font-medium">{title || "Document.pdf"}</div>
      </div>
    </div>
  )
}

function guessKind(name?: string | null) {
  const n = (name || "").toLowerCase()
  if (n.endsWith(".pdf")) return "pdf"
  if (n.match(/\.(png|jpg|jpeg|webp|gif)$/)) return "image"
  if (n.match(/\.(mp4|webm|mov|m4v|avi)$/)) return "video"
  if (n.match(/\.(mp3|wav|ogg|m4a)$/)) return "audio"
  return "file"
}

function AttachmentPreview({ a }: { a: any }) {
  const url = a.file
  const name = a.filename || "attachment"
  const kind = guessKind(name)

  function open() {
    if (!url) return
    window.open(url, "_blank", "noopener,noreferrer")
  }

  if (!url) return null

  if (kind === "pdf") {
    return <PdfThumb url={url} title={name} />
  }

  if (kind === "image") {
    return (
      <button
        type="button"
        onClick={open}
        className="w-full text-left rounded-2xl border bg-white hover:bg-black/5 transition p-3"
        style={{ borderColor: "rgba(16,185,129,0.18)" }}
      >
        <div className="flex items-start gap-3">
          <div className="h-20 w-20 rounded-xl overflow-hidden border bg-black/5 shrink-0" style={{ borderColor: "rgba(0,0,0,0.12)" }}>
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={url} alt={name} className="h-full w-full object-cover" />
          </div>
          <div className="min-w-0 flex-1">
            <div className="text-sm font-medium truncate">{name}</div>
            <div className="mt-1 text-xs text-muted-foreground">
              {a.content_type ? `${a.content_type}` : "—"} {a.size ? `• ${bytesToHuman(a.size)}` : ""}
            </div>
            <div className="mt-2 inline-flex items-center gap-1 text-[11px] text-emerald-700 underline">
              <ExternalLink className="h-3.5 w-3.5" /> Open
            </div>
          </div>
        </div>
      </button>
    )
  }

  // video/audio/file fallback (pro cards)
  const Icon =
    kind === "video" ? FileVideo2 :
    kind === "audio" ? FileAudio2 :
    File

  return (
    <button
      type="button"
      onClick={open}
      className="w-full text-left rounded-2xl border bg-white hover:bg-black/5 transition p-3"
      style={{ borderColor: "rgba(16,185,129,0.18)" }}
    >
      <div className="flex items-start gap-3">
        <div
          className="h-12 w-12 rounded-xl border flex items-center justify-center shrink-0"
          style={{ borderColor: "rgba(0,0,0,0.12)", background: "rgba(16,185,129,0.08)" }}
        >
          <Icon className="h-5 w-5 text-emerald-700" />
        </div>

        <div className="min-w-0 flex-1">
          <div className="text-sm font-medium truncate">{name}</div>
          <div className="mt-1 text-xs text-muted-foreground">
            {a.content_type ? `${a.content_type}` : "—"} {a.size ? `• ${bytesToHuman(a.size)}` : ""}
          </div>
          <div className="mt-2 inline-flex items-center gap-1 text-[11px] text-emerald-700 underline">
            <ExternalLink className="h-3.5 w-3.5" /> Open
          </div>
        </div>
      </div>
    </button>
  )
}

export default function ClientSupportTicketDetailPage() {
  const t = useTranslations("clientPortal")
  const locale = useLocale()
  const params = useParams<{ id: string }>()
  const search = useSearchParams()

  const ticketId = Number(params.id)
  const createdFlag = search?.get("created") === "1"

  const [ticket, setTicket] = useState<SupportTicket | null>(null)
  const [msgs, setMsgs] = useState<TicketMessage[]>([])
  const [loading, setLoading] = useState(false)
  const [err, setErr] = useState<string | null>(null)

  const [body, setBody] = useState("")
  const [files, setFiles] = useState<File[]>([])
  const [posting, setPosting] = useState(false)

  const [success, setSuccess] = useState<string | null>(null)

  const header = useMemo(() => {
    if (!ticket) return `#${ticketId}`
    return `#${ticket.id} • ${ticket.subject}`
  }, [ticket, ticketId])

  async function load() {
    if (!Number.isFinite(ticketId)) return
    setLoading(true)
    setErr(null)
    try {
      const [tkt, ms] = await Promise.all([
        getSupportTicket(ticketId),
        listTicketMessages(ticketId),
      ])
      setTicket(tkt)
      setMsgs(ms)
    } catch (e: any) {
      setErr(e?.message || t("common.error"))
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    load()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ticketId])

  useEffect(() => {
    if (createdFlag) {
      setSuccess(locale === "fr" ? "Ticket créé avec succès." : "Ticket created successfully.")
      const to = setTimeout(() => setSuccess(null), 4500)
      return () => clearTimeout(to)
    }
  }, [createdFlag, locale])

  async function send() {
    const v = body.trim()
    if (!v || posting) return

    const msg = validateFilesFront(files)
    if (msg) {
      setErr(msg)
      return
    }

    setPosting(true)
    setErr(null)
    try {
      const created = await addTicketMessage(ticketId, { body: v, files })
      setMsgs((prev) => [created, ...prev])
      setBody("")
      setFiles([])

      setSuccess(locale === "fr" ? "Message envoyé." : "Message sent.")
      setTimeout(() => setSuccess(null), 3500)

      const fresh = await getSupportTicket(ticketId)
      setTicket(fresh)
    } catch (e: any) {
      setErr(e?.message || t("common.error"))
    } finally {
      setPosting(false)
    }
  }

  async function closeTicket() {
    if (!ticket) return
    setErr(null)
    try {
      const updated = await patchTicket(ticketId, { status: "closed" })
      setTicket(updated)
      setSuccess(locale === "fr" ? "Ticket fermé." : "Ticket closed.")
      setTimeout(() => setSuccess(null), 3500)
    } catch (e: any) {
      setErr(e?.message || t("common.error"))
    }
  }

  async function reopenTicket() {
    if (!ticket) return
    setErr(null)
    try {
      const updated = await patchTicket(ticketId, { status: "open" })
      setTicket(updated)
      setSuccess(locale === "fr" ? "Ticket réouvert." : "Ticket reopened.")
      setTimeout(() => setSuccess(null), 3500)
    } catch (e: any) {
      setErr(e?.message || t("common.error"))
    }
  }

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-start justify-between gap-3">
        <div className="space-y-1">
          <div className="flex items-center gap-2">
            <LifeBuoy className="h-5 w-5 text-emerald-600" />
            <h1 className="text-xl font-semibold">{t("support.ticket.title")}</h1>
          </div>
          <div className="text-sm text-muted-foreground">{header}</div>
        </div>

        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={load}
            className="inline-flex items-center gap-2 rounded-xl border bg-white px-3 py-2 text-sm hover:bg-black/5"
            style={{ borderColor: "rgba(15,23,42,.08)" }}
          >
            <RefreshCw className="h-4 w-4" />
            {t("common.refresh")}
          </button>

          <Link
            href={`/${locale}/client/support`}
            className="inline-flex items-center gap-2 rounded-xl border bg-white px-3 py-2 text-sm hover:bg-black/5"
            style={{ borderColor: "rgba(15,23,42,.08)" }}
          >
            <ArrowLeft className="h-4 w-4" />
            {t("common.back")}
          </Link>
        </div>
      </div>

      {/* Alerts */}
      {err ? <div className="rounded-xl border border-red-200 bg-red-50 p-3 text-sm text-red-700">{err}</div> : null}
      {success ? (
        <div className="rounded-xl border p-3 text-sm flex items-center gap-2"
             style={{ borderColor: "rgba(16,185,129,0.25)", background: "rgba(16,185,129,0.10)" }}>
          <CheckCircle2 className="h-4 w-4 text-emerald-700" />
          <span className="text-emerald-900">{success}</span>
        </div>
      ) : null}

      {loading || !ticket ? (
        <div className="rounded-xl border p-3 text-sm flex items-center gap-2" style={{ borderColor: "rgba(15,23,42,.08)" }}>
          <Loader2 className="h-4 w-4 animate-spin" />
          {t("common.loading")}
        </div>
      ) : (
        <>
          {/* Ticket summary card */}
          <div className="rounded-2xl border bg-white p-4 space-y-3" style={{ borderColor: "rgba(15,23,42,.08)" }}>
            <div className="flex flex-col md:flex-row md:items-start md:justify-between gap-3">
              <div className="min-w-0">
                <div className="text-lg font-semibold text-slate-900 truncate">{ticket.subject}</div>

                <div className="mt-2 flex flex-wrap items-center gap-2">
                  <Badge label={t(`support.status.${ticket.status}`)} tone={statusTone(ticket.status)} />
                  <Badge label={t(`support.priority.${ticket.priority}`)} tone={priorityTone(ticket.priority)} />
                  <span className="text-xs text-slate-500">
                    {fmtTime(ticket.last_activity_at)}
                  </span>
                </div>

                {ticket.case_id ? (
                  <div className="mt-2 text-xs text-slate-600">
                    {t("support.ticket.linkedCase")}: <span className="font-medium">#{ticket.case_id}</span>
                  </div>
                ) : null}
              </div>

              <div className="flex items-center gap-2">
                {ticket.status !== "closed" ? (
                  <button
                    type="button"
                    onClick={closeTicket}
                    className="rounded-xl border bg-white px-3 py-2 text-sm hover:bg-black/5"
                    style={{ borderColor: "rgba(15,23,42,.08)" }}
                  >
                    {t("support.ticket.close")}
                  </button>
                ) : (
                  <button
                    type="button"
                    onClick={reopenTicket}
                    className="rounded-xl bg-emerald-600 px-3 py-2 text-sm font-medium text-white hover:bg-emerald-700"
                  >
                    {t("support.ticket.reopen")}
                  </button>
                )}
              </div>
            </div>

            <div
              className="rounded-xl border p-3 flex items-start gap-3"
              style={{ borderColor: "rgba(245,158,11,0.30)", background: "rgba(245,158,11,0.10)" }}
            >
              <ShieldAlert className="h-5 w-5 text-amber-700" />
              <div className="min-w-0">
                <div className="text-sm font-semibold text-amber-900">{t("support.security.title")}</div>
                <div className="mt-1 text-sm text-amber-900/80">{t("support.security.body")}</div>
              </div>
            </div>
          </div>

          {/* Composer */}
          <div className="rounded-2xl border bg-white p-4 space-y-3" style={{ borderColor: "rgba(15,23,42,.08)" }}>
            <div className="text-sm font-semibold">{t("support.ticket.replyTitle")}</div>

            <textarea
              className="w-full min-h-[120px] rounded-xl border px-3 py-2 text-sm"
              style={{ borderColor: "rgba(15,23,42,.08)" }}
              value={body}
              onChange={(e) => setBody(e.target.value)}
              placeholder={t("support.ticket.replyPlaceholder")}
              disabled={posting}
            />

            <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
              <label
                className="inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-sm cursor-pointer hover:bg-black/5"
                style={{ borderColor: "rgba(15,23,42,.08)" }}
              >
                <Paperclip className="h-4 w-4 text-emerald-700" />
                {t("support.ticket.attach")}
                <input
                  type="file"
                  className="hidden"
                  multiple
                  accept={FILE_ACCEPT}
                  onChange={(e) => {
                    const picked = Array.from(e.target.files || [])
                    const msg = validateFilesFront(picked)
                    if (msg) {
                      setErr(msg)
                      e.currentTarget.value = ""
                      return
                    }
                    setFiles(picked)
                  }}
                  disabled={posting}
                />
              </label>

              <div className="text-xs text-muted-foreground">
                {files.length > 0
                  ? `${files.length} file(s) selected • max 10MB/file • 20MB total`
                  : `max 10MB/file • 20MB total`}
              </div>

              <button
                type="button"
                onClick={send}
                disabled={posting || !body.trim()}
                className="inline-flex items-center gap-2 rounded-xl bg-emerald-600 px-4 py-2 text-sm font-medium text-white hover:bg-emerald-700 disabled:opacity-50"
              >
                {posting ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
                {t("support.ticket.send")}
              </button>
            </div>
          </div>

          {/* Timeline */}
          <div className="rounded-2xl border bg-white overflow-hidden" style={{ borderColor: "rgba(15,23,42,.08)" }}>
            {msgs.length === 0 ? (
              <div className="p-6 text-sm text-muted-foreground">{t("support.ticket.noMessages")}</div>
            ) : (
              msgs.map((m: any) => {
                const sideLabel =
                  m.side === "customer"
                    ? t("support.ticket.sideCustomer")
                    : m.side === "tenant"
                    ? t("support.ticket.sideTenant")
                    : t("support.ticket.sidePlatform")

                const bubble =
                  m.side === "customer"
                    ? { bg: "rgba(16,185,129,0.08)", bd: "rgba(16,185,129,0.18)" }
                    : { bg: "rgba(15,23,42,0.04)", bd: "rgba(15,23,42,0.10)" }

                return (
                  <div key={m.id} className="border-b p-4" style={{ borderColor: "rgba(15,23,42,.06)" }}>
                    <div className="text-xs text-muted-foreground">
                      <span className="font-medium">@{m.author?.username || "—"}</span> • {fmtTime(m.created_at)} • {sideLabel}
                    </div>

                    <div
                      className="mt-2 rounded-2xl border p-3 text-sm whitespace-pre-wrap"
                      style={{ background: bubble.bg, borderColor: bubble.bd }}
                    >
                      {m.body}
                    </div>

                    {m.attachments?.length ? (
                      <div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-3">
                        {m.attachments.map((a: any) => (
                          <AttachmentPreview key={a.id} a={a} />
                        ))}
                      </div>
                    ) : null}
                  </div>
                )
              })
            )}
          </div>
        </>
      )}
    </div>
  )
}
