import { useCallback, useState } from "react";
import {
  Pencil,
  Pin,
  PinOff,
  SmilePlus,
  Trash2,
  MessageSquarePlus,
  Copy,
  MoreHorizontal,
  CornerDownRight,
  Reply,
} from "lucide-react";
import { api } from "@/client";
import { cn } from "@/lib/utils";
import { workspaceColor, workspaceInitial } from "@/components/shell/shared";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Textarea } from "@/components/ui/textarea";
import type { MessageNewService } from "@/socket";
import type { Thread } from "./thread-sidebar";
import MessageContent from "./message-content";

export function formatTime(iso: string) {
  const d = new Date(iso);
  return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
}

export function formatDate(iso: string) {
  const d = new Date(iso);
  const now = new Date();
  if (d.toDateString() === now.toDateString()) return "Today";
  const yesterday = new Date(now);
  yesterday.setDate(yesterday.getDate() - 1);
  if (d.toDateString() === yesterday.toDateString()) return "Yesterday";
  return d.toLocaleDateString([], {
    month: "long",
    day: "numeric",
    year: d.getFullYear() !== now.getFullYear() ? "numeric" : undefined,
  });
}

export function DateDivider({ date }: { date: string }) {
  return (
    <div className="flex items-center gap-3 px-6 py-5">
      <div className="h-px flex-1 bg-gradient-to-r from-transparent via-border/30 to-border/30" />
      <span className="shrink-0 rounded-lg bg-muted/30 px-3 py-1 text-[11px] font-semibold text-muted-foreground/40 tracking-wide uppercase border border-border/20">
        {date}
      </span>
      <div className="h-px flex-1 bg-gradient-to-l from-transparent via-border/30 to-border/30" />
    </div>
  );
}

type Props = {
  message: MessageNewService;
  messages?: MessageNewService[];
  showHeader: boolean;
  isCompact: boolean;
  currentUserId?: string;
  roomId: string;
  onReply?: (message: MessageNewService) => void;
  onPinToggle?: (messageId: string, pinned: boolean) => void;
  onDelete?: (messageId: string) => void;
  onEdit?: (messageId: string, content: string) => void;
  onStartThread?: (messageId: string, seq: number) => void;
  onViewThread?: (threadId: string, seq: number) => void;
  onReactionToggle?: (messageId: string, emoji: string, add: boolean) => void;
  threads?: Thread[];
};

export default function MessageItem({
  message,
  messages,
  showHeader,
  isCompact,
  currentUserId,
  roomId,
  onReply,
  onPinToggle,
  onDelete,
  onEdit,
  onStartThread,
  onViewThread,
  onReactionToggle,
  threads,
}: Props) {
  const [editing, setEditing] = useState(false);
  const [editContent, setEditContent] = useState(message.content);
  const [saving, setSaving] = useState(false);

  const name =
    message.sender.display_name || message.sender.username || "Unknown";
  const initial = workspaceInitial(name);
  const colorClass = workspaceColor(name);
  const isOwn = currentUserId && message.sender.id === currentUserId;
  const isPinned = (message as Record<string, unknown>).pinned as
    | boolean
    | undefined;

  const threadForMessage = threads?.find((t) => t.parent_seq === message.seq);

  // Look up the replied-to message from the local message list
  const repliedMessage = message.in_reply_to
    ? messages?.find((m) => m.id === message.in_reply_to)
    : undefined;
  const replyAuthor =
    repliedMessage?.sender.display_name ??
    repliedMessage?.sender.username ??
    undefined;
  const replyPreview = repliedMessage?.content.slice(0, 80);

  const handleReaction = useCallback(
    (emoji: string) => {
      const existing = message.reactions?.find(
        (r) => r.emoji === emoji && r.reacted_by_me,
      );
      onReactionToggle?.(message.id, emoji, !existing);
      if (existing) {
        api
          .delete(`/api/v1/ws/rooms/${roomId}/reactions`, {
            data: { message: message.id, emoji },
          })
          .catch(() => {
            onReactionToggle?.(message.id, emoji, true);
          });
      } else {
        api
          .post(`/api/v1/ws/rooms/${roomId}/reactions`, {
            message: message.id,
            emoji,
          })
          .catch(() => {
            onReactionToggle?.(message.id, emoji, false);
          });
      }
    },
    [message.id, message.reactions, roomId, onReactionToggle],
  );

  const handleSaveEdit = useCallback(async () => {
    const trimmed = editContent.trim();
    if (!trimmed || trimmed === message.content) {
      setEditing(false);
      setEditContent(message.content);
      return;
    }
    setSaving(true);
    try {
      await api.patch(`/api/v1/ws/messages/${message.id}`, {
        content: trimmed,
      });
      onEdit?.(message.id, trimmed);
      setEditing(false);
    } catch {
      // ignore
    } finally {
      setSaving(false);
    }
  }, [editContent, message.content, message.id, onEdit]);

  const handleEditKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === "Escape") {
        setEditing(false);
        setEditContent(message.content);
      } else if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        handleSaveEdit();
      }
    },
    [handleSaveEdit, message.content],
  );

  return (
    <div
      className={cn(
        "group relative flex gap-3 transition-colors duration-150",
        isCompact
          ? "items-start px-4 py-0 hover:bg-muted/30"
          : "items-start px-4 py-1 hover:bg-muted/40",
      )}
    >
      {isCompact ? (
        <div className="w-10 shrink-0 text-center">
          <span className="mt-1 inline-block text-[10px] text-muted-foreground/0 transition-opacity duration-150 group-hover:text-muted-foreground/50">
            {formatTime(message.send_at)}
          </span>
        </div>
      ) : (
        <div
          className={cn(
            "grid size-10 shrink-0 place-items-center rounded-[10px] bg-gradient-to-br text-[13px] font-bold text-white shadow-sm ring-1 ring-white/10",
            colorClass,
          )}
        >
          {message.sender.avatar_url ? (
            <img
              alt={name}
              className="size-full rounded-[10px] object-cover"
              src={message.sender.avatar_url}
            />
          ) : (
            initial
          )}
        </div>
      )}

      <div className="min-w-0 flex-1">
        {!isCompact && showHeader && (
          <div className="flex items-center gap-2">
            <span className="cursor-pointer text-[15px] font-bold text-foreground transition-colors hover:text-primary">
              {name}
            </span>
            <span className="text-[11px] font-medium text-muted-foreground/35">
              {formatTime(message.send_at)}
            </span>
            {message.sender_type !== "user" && (
              <span className="rounded-full border border-primary/10 bg-primary/[0.05] px-1.5 py-[1px] text-[10px] font-semibold uppercase tracking-wide text-primary/60">
                {message.sender_type}
              </span>
            )}
            {isPinned && (
              <span className="text-warning/60" title="Pinned">
                <Pin className="size-3" />
              </span>
            )}
          </div>
        )}

        {/* Reply context indicator */}
        {message.in_reply_to && (
          <button
            className={cn(
              "mb-1 flex w-full items-center gap-1.5 rounded-lg border border-border/30 bg-muted/20 px-2.5 py-1 text-left",
              repliedMessage && "cursor-pointer transition-colors hover:border-border/50 hover:bg-muted/40",
              !repliedMessage && "cursor-default",
            )}
            disabled={!repliedMessage}
            onClick={() => {
              if (repliedMessage) onReply?.(repliedMessage);
            }}
            title={replyPreview ? `Replying to: ${replyPreview}` : "Replying to a message"}
            type="button"
          >
            <CornerDownRight className="size-3 shrink-0 text-primary/50" />
            {replyAuthor ? (
              <span className="truncate text-[11px] font-semibold text-primary/60">
                {replyAuthor}
              </span>
            ) : (
              <span className="text-[11px] text-muted-foreground/40">
                Original message
              </span>
            )}
            {replyPreview && (
              <span className="truncate text-[11px] text-muted-foreground/40">
                {replyPreview}
              </span>
            )}
          </button>
        )}

        {editing ? (
          <div className="mt-1 space-y-2">
            <Textarea
              autoFocus
              className="min-h-[56px] resize-none rounded-lg border-border/60 bg-muted/30 text-sm focus-visible:ring-1 focus-visible:ring-primary/20"
              disabled={saving}
              onBlur={handleSaveEdit}
              onChange={(e) => setEditContent(e.target.value)}
              onKeyDown={handleEditKeyDown}
              value={editContent}
            />
            <div className="flex items-center gap-2 text-[11px] text-muted-foreground/40">
              <span>Esc to cancel · Enter to save</span>
            </div>
          </div>
        ) : (
          <MessageContent
            content={message.content}
            contentType={message.content_type}
          />
        )}

        {threadForMessage && !message.thread && (
          <button
            className="mt-1.5 flex items-center gap-1.5 rounded-lg border border-border/30 bg-muted/20 px-2.5 py-1 text-[12px] font-medium text-primary/70 transition-[background-color,border-color,color,box-shadow] duration-150 hover:border-primary/20 hover:bg-primary/10 hover:text-primary hover:shadow-sm"
            onClick={() => onViewThread?.(threadForMessage.id, message.seq)}
            type="button"
          >
            <MessageSquarePlus className="size-3.5" />
            <span>View thread</span>
          </button>
        )}

        {message.reactions && message.reactions.length > 0 && (
          <div className="mt-1.5 flex flex-wrap gap-1.5">
            {message.reactions.map((r) => (
              <button
                className={cn(
                  "inline-flex cursor-pointer items-center gap-1 rounded-lg border px-2 py-[2px] text-xs transition-[background-color,border-color,color] duration-150",
                  r.reacted_by_me
                    ? "border-primary/15 bg-primary/[0.06] text-primary hover:bg-primary/[0.1]"
                    : "border-border/30 bg-muted/20 text-muted-foreground/60 hover:border-border/50 hover:bg-muted/40",
                )}
                key={r.emoji}
                onClick={() => handleReaction(r.emoji)}
                title={r.reacted_by_me ? "Click to remove" : "Click to add"}
              >
                <span className="text-[13px]">{r.emoji}</span>
                <span className="text-[10px] font-semibold tabular-nums">{r.count}</span>
              </button>
            ))}
            <ReactionPicker
              onSelect={(emoji) => handleReaction(emoji)}
              trigger={
                <button aria-label="Add reaction" className="inline-flex size-8 cursor-pointer items-center justify-center rounded-lg border border-dashed border-border/30 text-muted-foreground/30 opacity-60 transition-[border-color,color,opacity] duration-150 hover:border-primary/25 hover:text-primary/60 group-hover:opacity-100" type="button">
                  <SmilePlus className="size-3" />
                </button>
              }
            />
          </div>
        )}
      </div>

      <div className="absolute right-2 top-0 z-10 flex items-center gap-[1px] rounded-xl border border-border/30 bg-card/95 px-1 py-1 opacity-0 shadow-md backdrop-blur-sm transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100">
        <ReactionPicker
          onSelect={(emoji) => handleReaction(emoji)}
          trigger={
            <Button
              aria-label="Add reaction"
              className="size-8 cursor-pointer rounded-lg text-muted-foreground/50 hover:bg-accent/50 hover:text-foreground"
              size="icon"
              title="Add reaction"
              variant="ghost"
            >
              <SmilePlus className="size-3.5" />
            </Button>
          }
        />

        <Button
          aria-label="Reply"
          className="size-8 cursor-pointer rounded-lg text-muted-foreground/50 hover:bg-accent/50 hover:text-foreground"
          onClick={() => onReply?.(message)}
          size="icon"
          title="Reply"
          variant="ghost"
        >
          <Reply className="size-3.5" />
        </Button>

        <Button
          aria-label={threadForMessage ? "View thread" : "Start thread"}
          className="size-8 cursor-pointer rounded-lg text-muted-foreground/50 hover:bg-accent/50 hover:text-foreground"
          onClick={() =>
            threadForMessage
              ? onViewThread?.(threadForMessage.id, message.seq)
              : onStartThread?.(message.id, message.seq)
          }
          size="icon"
          title={threadForMessage ? "View thread" : "Start thread"}
          variant="ghost"
        >
          <MessageSquarePlus className="size-3.5" />
        </Button>

        <DropdownMenu>
          <DropdownMenuTrigger>
            <Button
              aria-label="More message actions"
              className="size-8 cursor-pointer rounded-lg text-muted-foreground/50 hover:bg-accent/50 hover:text-foreground"
              size="icon"
              title="More"
              variant="ghost"
            >
              <MoreHorizontal className="size-3.5" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-44">
            <DropdownMenuItem
              className="cursor-pointer text-[13px]"
              onClick={() => onReply?.(message)}
            >
              <Reply className="mr-2 size-4" />
              Reply
            </DropdownMenuItem>

            <DropdownMenuItem
              className="cursor-pointer text-[13px]"
              onClick={() => {
                navigator.clipboard.writeText(message.content);
              }}
            >
              <Copy className="mr-2 size-4" />
              Copy text
            </DropdownMenuItem>

            {isOwn && (
              <DropdownMenuItem
                className="cursor-pointer text-[13px]"
                onClick={() => {
                  setEditContent(message.content);
                  setEditing(true);
                }}
              >
                <Pencil className="mr-2 size-4" />
                Edit message
              </DropdownMenuItem>
            )}

            {isOwn && (
              <DropdownMenuItem
                className="cursor-pointer text-[13px] text-destructive focus:text-destructive"
                onClick={() => onDelete?.(message.id)}
              >
                <Trash2 className="mr-2 size-4" />
                Delete message
              </DropdownMenuItem>
            )}

            <DropdownMenuSeparator />

            <DropdownMenuItem
              className="cursor-pointer text-[13px]"
              onClick={() => onPinToggle?.(message.id, !isPinned)}
            >
              {isPinned ? (
                <>
                  <PinOff className="mr-2 size-4" />
                  Unpin message
                </>
              ) : (
                <>
                  <Pin className="mr-2 size-4" />
                  Pin message
                </>
              )}
            </DropdownMenuItem>

            <DropdownMenuItem
              className="cursor-pointer text-[13px]"
              onClick={() =>
                threadForMessage
                  ? onViewThread?.(threadForMessage.id, message.seq)
                  : onStartThread?.(message.id, message.seq)
              }
            >
              <MessageSquarePlus className="mr-2 size-4" />
              {threadForMessage ? "View thread" : "Start thread"}
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </div>
  );
}

const REACTIONS_PALETTE = [
  "👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀",
  "✅", "❌", "🔥", "💯", "🤔", "🙌", "😢", "🤯",
];

function ReactionPicker({
  trigger,
  onSelect,
}: {
  trigger: React.ReactElement;
  onSelect: (emoji: string) => void;
}) {
  return (
    <Popover>
      <PopoverTrigger render={trigger} />
      <PopoverContent
        align="start"
        className="w-auto p-2"
        side="top"
        sideOffset={8}
      >
        <div className="grid grid-cols-8 gap-0.5">
          {REACTIONS_PALETTE.map((emoji) => (
            <button
              className="grid size-9 cursor-pointer place-items-center rounded-lg text-lg transition-[background-color,transform] duration-150 hover:scale-105 hover:bg-accent/50"
              key={emoji}
              onClick={() => onSelect(emoji)}
              title={emoji}
            >
              {emoji}
            </button>
          ))}
        </div>
      </PopoverContent>
    </Popover>
  );
}
