"use client";

import { useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { toast } from "sonner";
import { ExternalLink, FileText, MessageSquare } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

type TicketStatus = "open" | "triaged" | "closed";

type Attachment = { id: string; contentType: string; url: string };

type Comment = { id: string; authorType: "user" | "admin" | "gitea"; body: string; createdAt: string };

const AUTHOR_LABEL: Record<Comment["authorType"], string> = { user: "User", admin: "Admin", gitea: "Gitea" };

type Ticket = {
  id: string;
  userEmail: string;
  username: string | null;
  type: string;
  title: string;
  description: string;
  status: TicketStatus;
  giteaIssueUrl: string | null;
  giteaError: string | null;
  createdAt: string;
  attachments: Attachment[];
};

function isImage(contentType: string) {
  return contentType.startsWith("image/");
}

function formatDateTime(iso: string) {
  return new Date(iso).toLocaleString(undefined, {
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

const statusVariant: Record<TicketStatus, "default" | "secondary" | "outline"> = {
  open: "default",
  triaged: "secondary",
  closed: "outline",
};

export function AdminSupportManager({ initialTickets }: { initialTickets: Ticket[] }) {
  const [tickets, setTickets] = useState<Ticket[]>(initialTickets);
  const [retrying, setRetrying] = useState<string | null>(null);
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [comments, setComments] = useState<Record<string, Comment[]>>({});
  const [commentDraft, setCommentDraft] = useState("");
  const [sendingComment, setSendingComment] = useState(false);

  async function toggleConversation(ticketId: string) {
    if (expandedId === ticketId) {
      setExpandedId(null);
      return;
    }
    setExpandedId(ticketId);
    setCommentDraft("");
    if (!comments[ticketId]) {
      try {
        const res = await fetch(`/api/v1/admin/support/${ticketId}/comments`);
        if (res.ok) {
          const data = (await res.json()) as Comment[];
          setComments((prev) => ({ ...prev, [ticketId]: data }));
        }
      } catch {
        // leave the section empty — the send box below still works
      }
    }
  }

  async function sendComment(ticketId: string) {
    const body = commentDraft.trim();
    if (!body) return;
    setSendingComment(true);
    try {
      const res = await fetch(`/api/v1/admin/support/${ticketId}/comments`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ body }),
      });
      if (!res.ok) throw new Error();
      const comment = (await res.json()) as Comment;
      setComments((prev) => ({ ...prev, [ticketId]: [...(prev[ticketId] ?? []), comment] }));
      setCommentDraft("");
    } catch {
      toast.error("Failed to send comment");
    } finally {
      setSendingComment(false);
    }
  }

  async function handleStatusChange(id: string, status: TicketStatus) {
    try {
      const res = await fetch(`/api/v1/admin/support/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ status }),
      });
      if (!res.ok) throw new Error();
      setTickets((prev) => prev.map((t) => (t.id === id ? { ...t, status } : t)));
    } catch {
      toast.error("Failed to update status");
    }
  }

  async function handleRetryGitea(id: string) {
    setRetrying(id);
    try {
      const res = await fetch(`/api/v1/admin/support/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ retryGitea: true }),
      });
      if (!res.ok) throw new Error();
      // Re-fetch the single ticket's fields isn't wired up server-side, so
      // reload the list to pick up the new giteaIssueUrl/giteaError.
      const listRes = await fetch("/api/v1/admin/support");
      if (listRes.ok) {
        const data = (await listRes.json()) as Ticket[];
        setTickets(data);
      }
      toast.success("Retried Gitea issue creation");
    } catch {
      toast.error("Retry failed");
    } finally {
      setRetrying(null);
    }
  }

  if (tickets.length === 0) {
    return <p className="text-sm text-muted-foreground">No support tickets yet.</p>;
  }

  return (
    <div className="divide-y rounded-md border">
      {tickets.map((ticket) => (
        <div key={ticket.id} className="px-4 py-3 space-y-1.5">
          <div className="flex items-start justify-between gap-4">
            <div className="min-w-0">
              <p className="text-sm font-medium">{ticket.title}</p>
              <p className="text-xs text-muted-foreground">
                {ticket.username ? `@${ticket.username}` : ticket.userEmail} · {formatDateTime(ticket.createdAt)}
              </p>
            </div>
            <Select value={ticket.status} onValueChange={(v) => { void handleStatusChange(ticket.id, v as TicketStatus); }}>
              <SelectTrigger className="w-32 shrink-0">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="open">Open</SelectItem>
                <SelectItem value="triaged">Triaged</SelectItem>
                <SelectItem value="closed">Closed</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <p className="text-sm text-muted-foreground whitespace-pre-wrap">{ticket.description}</p>
          {ticket.attachments.length > 0 && (
            <div className="flex flex-wrap gap-2 pt-1">
              {ticket.attachments.map((a) => (
                <Link
                  key={a.id}
                  href={a.url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="relative h-12 w-12 rounded-md border overflow-hidden block"
                >
                  {isImage(a.contentType) ? (
                    <Image src={a.url} unoptimized alt="Attachment" fill className="object-cover" />
                  ) : (
                    <div className="h-full w-full flex items-center justify-center bg-muted/40">
                      <FileText className="h-4 w-4 text-muted-foreground" />
                    </div>
                  )}
                </Link>
              ))}
            </div>
          )}
          <div className="flex items-center gap-2 text-xs flex-wrap pt-1">
            <Badge variant="outline" className="text-xs">{ticket.type}</Badge>
            <Badge variant={statusVariant[ticket.status]} className="text-xs">{ticket.status}</Badge>
            {ticket.giteaIssueUrl ? (
              <Link
                href={ticket.giteaIssueUrl}
                target="_blank"
                rel="noopener noreferrer"
                className="flex items-center gap-1 text-primary hover:underline"
              >
                View Gitea issue
                <ExternalLink className="h-3 w-3" />
              </Link>
            ) : (
              <>
                {ticket.giteaError && (
                  <span className="text-destructive" title={ticket.giteaError}>Gitea issue failed</span>
                )}
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-6 px-2 text-xs"
                  disabled={retrying === ticket.id}
                  onClick={() => { void handleRetryGitea(ticket.id); }}
                >
                  {retrying === ticket.id ? "Retrying…" : "Create Gitea issue"}
                </Button>
              </>
            )}
            <button
              type="button"
              onClick={() => { void toggleConversation(ticket.id); }}
              className="flex items-center gap-1 text-muted-foreground hover:text-foreground"
            >
              <MessageSquare className="h-3 w-3" />
              Conversation
            </button>
          </div>

          {expandedId === ticket.id && (
            <div className="mt-2 space-y-2 rounded-md border bg-muted/30 p-3">
              {(comments[ticket.id] ?? []).length === 0 ? (
                <p className="text-xs text-muted-foreground">No comments yet.</p>
              ) : (
                <div className="space-y-2">
                  {(comments[ticket.id] ?? []).map((c) => (
                    <div key={c.id} className="text-sm">
                      <span className="text-xs font-medium text-muted-foreground">{AUTHOR_LABEL[c.authorType]}</span>
                      <p className="whitespace-pre-wrap">{c.body}</p>
                    </div>
                  ))}
                </div>
              )}
              <div className="flex gap-2 pt-1">
                <Textarea
                  value={commentDraft}
                  onChange={(e) => setCommentDraft(e.target.value)}
                  placeholder="Reply to this ticket…"
                  maxLength={3000}
                  rows={2}
                  className="text-sm"
                />
                <Button
                  type="button"
                  size="sm"
                  disabled={sendingComment || !commentDraft.trim()}
                  onClick={() => { void sendComment(ticket.id); }}
                >
                  Send
                </Button>
              </div>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}
