import {
  AlertCircle,
  CheckCircle2,
  ChevronDown,
  ChevronUp,
  Image as ImageIcon,
  Pencil,
  RotateCw,
  Smile,
  Trash2,
} from "lucide-react";
import { Fragment, useMemo, useState } from "react";
import { parseMetadata } from "../../../entities/message/types";
import type { MessageRecord } from "../../../shared/api/client";
import { Badge, Button, Skeleton } from "../../../shared/ui";

const CUSTOM_EMOJI_REGEX = /<(a)?:([a-zA-Z0-9_]+):(\d+)>/g;

/**
 * Renders message content with Discord custom emojis displayed as images
 * instead of raw text like `<:name:id>`.
 */
function renderContentWithCustomEmojis(content: string): React.ReactNode {
  const parts: React.ReactNode[] = [];
  const regex = new RegExp(CUSTOM_EMOJI_REGEX.source, "g");
  let lastIndex = 0;
  let match: RegExpExecArray | null;

  while ((match = regex.exec(content)) !== null) {
    // Text before the emoji
    if (match.index > lastIndex) {
      parts.push(content.slice(lastIndex, match.index));
    }

    const [, animated, name, id] = match;
    const ext = animated ? "gif" : "png";
    const url = `https://cdn.discordapp.com/emojis/${id}.${ext}?size=128`;

    parts.push(
      <img
        key={`${id}-${match.index}`}
        src={url}
        alt={name}
        className="inline-block h-[22px] w-[22px] align-middle object-contain"
        loading="lazy"
        draggable={false}
        title={`:${name}:`}
      />,
    );

    lastIndex = regex.lastIndex;
  }

  // Remaining text after last emoji
  if (lastIndex < content.length) {
    parts.push(content.slice(lastIndex));
  }

  // If no emojis were found, just return the raw content
  if (parts.length === 0) {
    return content;
  }

  return <Fragment>{parts}</Fragment>;
}

interface MessageCardProps {
  message: MessageRecord;
  onReanalyze: (id: string) => Promise<void>;
  compact?: boolean;
}

function parseStringList(value?: string | null): string[] {
  if (!value) return [];
  try {
    const parsed = JSON.parse(value) as unknown;
    return Array.isArray(parsed)
      ? parsed.filter((item): item is string => typeof item === "string")
      : [];
  } catch {
    return value
      .split(",")
      .map((item) => item.trim())
      .filter(Boolean);
  }
}

function aiVariant(status: string) {
  if (status === "clean") return "success";
  if (status === "flagged" || status === "error") return "destructive";
  return "secondary";
}

function severityColor(severity: string) {
  switch (severity) {
    case "critical":
      return "bg-red-100 text-red-700 border-red-200";
    case "high":
      return "bg-orange-100 text-orange-700 border-orange-200";
    case "medium":
      return "bg-yellow-100 text-yellow-700 border-yellow-200";
    case "low":
      return "bg-blue-100 text-blue-700 border-blue-200";
    default:
      return "bg-muted text-muted-foreground border-border";
  }
}

function formatTimeAgo(ts: number): string {
  const seconds = Math.floor((Date.now() - ts) / 1000);
  if (seconds < 60) return `${seconds}s ago`;
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return new Date(ts).toLocaleDateString();
}

export function MessageCard({
  message,
  onReanalyze,
  compact,
}: MessageCardProps) {
  const metadata = useMemo(
    () => parseMetadata(message.metadata),
    [message.metadata],
  );
  const displayContent = message.edited_content ?? message.content;
  const aiStatus = message.ai_status ?? "pending";
  const categories = useMemo(() => {
    const list = parseStringList(
      message.ai_categories ?? message.ai_moderation_flags,
    );
    return list.filter((c) => c !== "analysis_incomplete");
  }, [message.ai_categories, message.ai_moderation_flags]);
  const confidence =
    message.ai_confidence ?? message.ai_moderation_score ?? null;
  const [isReanalyzing, setIsReanalyzing] = useState(false);
  const [showAnalysis, setShowAnalysis] = useState(aiStatus === "flagged");

  // Build a human-readable analysis summary from categories + confidence + severity
  const analysisSummary = useMemo(() => {
    const parts: string[] = [];
    if (categories.length > 0) {
      parts.push(categories.slice(0, 3).join(", "));
      if (categories.length > 3) parts.push(`+${categories.length - 3} more`);
    }
    if (message.ai_severity && message.ai_severity !== "none") {
      parts.push(message.ai_severity);
    }
    if (confidence != null) {
      parts.push(`${Math.round(confidence * 100)}% confidence`);
    }
    if (parts.length === 0) return "View AI analysis";
    return parts.join(" · ");
  }, [categories, message.ai_severity, confidence]);

  const stickers = metadata.stickers ?? [];
  const attachments = metadata.attachments ?? [];
  const imageAttachments = attachments.filter(
    (a) =>
      a.contentType?.startsWith("image/") ||
      /\.(png|jpe?g|gif|webp)$/i.test(a.name),
  );
  const hasImages = imageAttachments.length > 0;

  const handleReanalyze = async () => {
    setIsReanalyzing(true);
    try {
      await onReanalyze(message.id);
    } finally {
      setIsReanalyzing(false);
    }
  };

  return (
    <article
      className={`group rounded-2xl border bg-white shadow-sm transition-all hover:border-primary/30 hover:shadow-md ${
        compact ? "px-4 py-1.5" : "p-4"
      } ${
        message.deleted_at ? "border-red-200 opacity-60" : "border-primary/20"
      }`}
    >
      <div className={`flex ${compact ? "gap-2" : "gap-3"}`}>
        {!compact && (
          <img
            src={
              message.avatar_url ??
              "https://cdn.discordapp.com/embed/avatars/0.png"
            }
            alt=""
            className="h-10 w-10 shrink-0 rounded-full object-cover ring-2 ring-primary/30"
          />
        )}
        <div
          className={`min-w-0 flex-1 ${compact ? "space-y-1" : "space-y-2.5"}`}
        >
          {!compact && (
            <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
              <span className="font-semibold text-foreground">
                {message.username || message.user_id}
              </span>
              <span
                className="text-xs text-muted-foreground"
                title={new Date(message.created_at).toLocaleString()}
              >
                {formatTimeAgo(message.created_at)}
              </span>
              {message.edited_at && (
                <span className="flex items-center gap-1 text-xs text-muted-foreground">
                  <Pencil className="h-3 w-3" /> edited
                </span>
              )}
              {message.deleted_at && (
                <span className="flex items-center gap-1 text-xs text-destructive">
                  <Trash2 className="h-3 w-3" /> deleted
                </span>
              )}
              <div className="ml-auto flex items-center gap-1.5">
                <Badge
                  variant={aiVariant(aiStatus)}
                  className="flex items-center gap-1 text-xs"
                >
                  {aiStatus === "clean" && (
                    <CheckCircle2 className="h-3.5 w-3.5" />
                  )}
                  {aiStatus === "flagged" && (
                    <AlertCircle className="h-3.5 w-3.5" />
                  )}
                  {aiStatus === "error" && (
                    <AlertCircle className="h-3.5 w-3.5" />
                  )}
                  {aiStatus}
                </Badge>
                {message.ai_severity && message.ai_severity !== "none" && (
                  <Badge
                    className={`text-xs ${severityColor(message.ai_severity)}`}
                  >
                    {message.ai_severity}
                  </Badge>
                )}
                {confidence != null && (
                  <Badge variant="outline" className="text-xs tabular-nums">
                    {Math.round(confidence * 100)}%
                  </Badge>
                )}
              </div>
            </div>
          )}

          {displayContent ? (
            <p className="whitespace-pre-wrap break-words text-sm leading-6 text-foreground/90">
              {renderContentWithCustomEmojis(displayContent)}
            </p>
          ) : null}

          {stickers.length > 0 && (
            <div className="flex flex-wrap gap-3">
              {stickers.map((sticker) => (
                <div
                  key={sticker.name || sticker.url}
                  className="flex items-center gap-2"
                >
                  {sticker.url ? (
                    <img
                      src={sticker.url}
                      alt={sticker.name || "sticker"}
                      className="h-16 w-16 rounded-xl border border-border object-contain bg-muted/50"
                      loading="lazy"
                    />
                  ) : (
                    <div className="flex h-16 w-16 items-center justify-center rounded-xl border border-border bg-muted/50">
                      <Smile className="h-8 w-8 text-muted-foreground" />
                    </div>
                  )}
                  <span
                    className="text-xs text-muted-foreground max-w-[120px] truncate"
                    title={sticker.name}
                  >
                    {sticker.name}
                  </span>
                </div>
              ))}
            </div>
          )}

          {hasImages && (
            <div className="flex gap-2 overflow-x-auto">
              {imageAttachments.slice(0, 4).map((img) => (
                <a
                  key={img.url}
                  href={img.url}
                  target="_blank"
                  rel="noreferrer"
                  className="shrink-0 overflow-hidden rounded-xl border border-border"
                >
                  <img
                    src={img.url}
                    alt={img.name}
                    className="h-20 w-20 object-cover transition-transform hover:scale-105"
                    loading="lazy"
                  />
                </a>
              ))}
              {imageAttachments.length > 4 && (
                <div className="flex h-20 w-20 items-center justify-center rounded-xl border border-border bg-muted text-xs text-muted-foreground">
                  +{imageAttachments.length - 4}{" "}
                  <ImageIcon className="ml-1 h-3 w-3" />
                </div>
              )}
            </div>
          )}

          {categories.length > 0 && (
            <div className="flex flex-wrap gap-1.5">
              {categories.map((category) => (
                <Badge key={category} variant="secondary" className="text-xs">
                  {category}
                </Badge>
              ))}
            </div>
          )}

          {message.ai_analysis ? (
            <div
              className={`rounded-xl border-l-4 p-3 ${
                aiStatus === "flagged"
                  ? "border-l-pink-400 bg-pink-50/50"
                  : "border-l-emerald-400 bg-emerald-50/50"
              }`}
            >
              <button
                type="button"
                onClick={() => setShowAnalysis(!showAnalysis)}
                className="flex w-full items-center justify-between gap-2 text-left text-xs"
              >
                <span className="font-medium text-foreground/80">
                  {aiStatus === "flagged" ? "🚨 " : "ℹ️ "}
                  {analysisSummary}
                </span>
                {showAnalysis ? (
                  <ChevronUp className="h-4 w-4 shrink-0 text-muted-foreground" />
                ) : (
                  <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
                )}
              </button>
              {showAnalysis && (
                <div className="mt-2 border-t border-border pt-2 text-sm text-muted-foreground leading-relaxed whitespace-pre-wrap">
                  {message.ai_analysis}
                </div>
              )}
            </div>
          ) : null}

          {message.ai_error ? (
            <div className="rounded-xl bg-pink-50/50 p-3 text-sm text-pink-700">
              AI error: {message.ai_error}
            </div>
          ) : null}

          <div className="flex items-center gap-2 pt-1">
            <Button
              size="sm"
              variant={aiStatus === "error" ? "destructive" : "outline"}
              onClick={handleReanalyze}
              disabled={aiStatus === "pending" || isReanalyzing}
              className="text-xs"
            >
              <RotateCw
                className={`h-3.5 w-3.5 ${isReanalyzing ? "animate-spin" : ""}`}
              />
              {isReanalyzing ? "Reanalyzing..." : "Re-analyze"}
            </Button>
            {aiStatus === "error" && (
              <span className="text-xs text-pink-600/80">
                Click to retry analysis
              </span>
            )}
          </div>
        </div>
      </div>
    </article>
  );
}

export function MessageCardSkeleton() {
  return (
    <article className="rounded-2xl border border-primary/20 bg-white p-4 shadow-sm">
      <div className="flex gap-3">
        <Skeleton className="h-10 w-10 shrink-0 rounded-full" />
        <div className="min-w-0 flex-1 space-y-3">
          <Skeleton className="h-5 w-48" />
          <Skeleton className="h-4 w-full" />
          <Skeleton className="h-4 w-3/4" />
          <div className="flex gap-2">
            <Skeleton className="h-6 w-16 rounded-full" />
            <Skeleton className="h-6 w-20 rounded-full" />
          </div>
        </div>
      </div>
    </article>
  );
}
