import { cn } from "@xtablo/shared";
import {
  ArrowDown,
  ArrowUp,
  Check,
  ChevronDown,
  ChevronRight,
  Pin,
  Search,
  Trash2,
  X,
} from "lucide-react";
import * as React from "react";
import { formatTimestamp } from "../hooks";
import type { ChatMessageData } from "../types";

// ─── ChatForwardDialog ────────────────────────────────────────────────────────

interface Conversation {
  id: string;
  title: string;
  avatar?: string;
}

interface ChatForwardDialogProps {
  message: ChatMessageData;
  conversations: Conversation[];
  onForward: (targetIds: string[]) => void;
  onCancel: () => void;
  className?: string;
}

function ChatForwardDialog({
  message,
  conversations,
  onForward,
  onCancel,
  className,
}: ChatForwardDialogProps) {
  const [query, setQuery] = React.useState("");
  const [selected, setSelected] = React.useState<Set<string>>(new Set());

  const filtered = conversations.filter((c) => c.title.toLowerCase().includes(query.toLowerCase()));

  const toggle = (id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  return (
    <div
      className={cn("fixed inset-0 z-50 flex items-center justify-center bg-black/50", className)}
    >
      <div className="w-full max-w-sm overflow-hidden rounded-xl border border-border bg-card shadow-lg">
        {/* Header */}
        <div className="flex items-center justify-between border-b border-border px-4 py-3">
          <span className="text-[14px] font-semibold text-foreground">Forward message</span>
          <button onClick={onCancel} className="text-muted-foreground/60 hover:text-foreground">
            <X className="size-4" />
          </button>
        </div>

        {/* Preview */}
        <div className="border-b border-border px-4 py-2">
          <span className="text-[12px] font-semibold text-muted-foreground">
            {message.senderName}
          </span>
          <p className="truncate text-[13px] text-muted-foreground/60">{message.text}</p>
        </div>

        {/* Search */}
        <div className="border-b border-border px-4 py-2">
          <div className="flex items-center gap-2 rounded-lg bg-background px-3 py-1.5">
            <Search className="size-3.5 text-muted-foreground/60" />
            <input
              type="text"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder="Search conversations..."
              className="flex-1 bg-transparent text-[13px] text-foreground placeholder:text-muted-foreground/60 outline-none"
            />
          </div>
        </div>

        {/* Conversation list */}
        <div className="max-h-60 overflow-y-auto">
          {filtered.map((c) => (
            <button
              key={c.id}
              onClick={() => toggle(c.id)}
              className={cn(
                "flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors",
                selected.has(c.id) ? "bg-accent" : "hover:bg-accent"
              )}
            >
              <div className="flex size-8 items-center justify-center rounded-full bg-muted text-[11px] font-semibold text-muted-foreground">
                {c.title.charAt(0).toUpperCase()}
              </div>
              <span className="flex-1 text-[14px] text-foreground">{c.title}</span>
              {selected.has(c.id) && <Check className="size-4 text-primary" />}
            </button>
          ))}
        </div>

        {/* Actions */}
        <div className="flex items-center justify-end gap-2 border-t border-border px-4 py-3">
          <button
            onClick={onCancel}
            className="rounded-lg px-3 py-1.5 text-[13px] font-medium text-muted-foreground hover:bg-accent"
          >
            Cancel
          </button>
          <button
            onClick={() => onForward(Array.from(selected))}
            disabled={selected.size === 0}
            className="rounded-lg bg-primary px-3 py-1.5 text-[13px] font-medium text-white disabled:opacity-40"
          >
            Forward{selected.size > 0 ? ` (${selected.size})` : ""}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── ChatEditComposer (inline edit mode) ──────────────────────────────────────

interface ChatEditComposerProps {
  message: ChatMessageData;
  onSave: (messageId: string, newText: string) => void;
  onCancel: () => void;
  className?: string;
}

function ChatEditComposer({ message, onSave, onCancel, className }: ChatEditComposerProps) {
  const [value, setValue] = React.useState(message.text || "");

  return (
    <div className={cn("border-t border-border", className)}>
      {/* Edit bar */}
      <div className="flex items-center gap-2 bg-amber-500/10 px-4 py-1.5">
        <span className="text-[12px] font-semibold text-amber-500">Editing message</span>
        <button
          onClick={onCancel}
          className="ml-auto text-[12px] text-muted-foreground hover:text-foreground"
        >
          Cancel
        </button>
      </div>
      <div className="flex items-end gap-2 bg-card px-3 py-2">
        <textarea
          value={value}
          onChange={(e) => setValue(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              onSave(message.id, value.trim());
            }
            if (e.key === "Escape") onCancel();
          }}
          rows={1}
          autoFocus
          className="flex-1 resize-none rounded-[20px] border border-border bg-card px-4 py-2 text-[15px] text-foreground outline-none"
        />
        <button
          onClick={() => onSave(message.id, value.trim())}
          disabled={!value.trim()}
          className="flex size-8 items-center justify-center rounded-full bg-primary text-white disabled:opacity-40"
        >
          <Check className="size-4" />
        </button>
      </div>
    </div>
  );
}

// ─── ChatDeletedMessage (placeholder) ─────────────────────────────────────────

interface ChatDeletedMessageProps {
  deletedBy?: string;
  className?: string;
}

function ChatDeletedMessage({ deletedBy, className }: ChatDeletedMessageProps) {
  return (
    <div className={cn("my-2 flex justify-center", className)}>
      <span className="rounded-lg bg-card px-3 py-1.5 text-[13px] italic text-muted-foreground/60">
        <Trash2 className="mr-1.5 inline size-3" />
        {deletedBy ? `${deletedBy} deleted this message` : "This message was deleted"}
      </span>
    </div>
  );
}

// ─── ChatPinnedPanel ──────────────────────────────────────────────────────────

interface ChatPinnedPanelProps {
  pinnedMessages: ChatMessageData[];
  onUnpin: (messageId: string) => void;
  onJumpTo: (messageId: string) => void;
  onClose: () => void;
  className?: string;
}

function ChatPinnedPanel({
  pinnedMessages,
  onUnpin,
  onJumpTo,
  onClose,
  className,
}: ChatPinnedPanelProps) {
  return (
    <div className={cn("flex h-full w-80 flex-col border-l border-border bg-card", className)}>
      <div className="flex items-center justify-between border-b border-border px-4 py-3">
        <div className="flex items-center gap-2">
          <Pin className="size-4 text-orange-500" />
          <span className="text-[14px] font-semibold text-foreground">
            Pinned Messages ({pinnedMessages.length})
          </span>
        </div>
        <button onClick={onClose} className="text-muted-foreground/60 hover:text-foreground">
          <X className="size-4" />
        </button>
      </div>
      <div className="flex-1 overflow-y-auto">
        {pinnedMessages.map((msg) => (
          <div
            key={msg.id}
            className="border-b border-border px-4 py-3 transition-colors hover:bg-accent"
          >
            <div className="flex items-center justify-between">
              <span className="text-[12px] font-semibold text-muted-foreground">
                {msg.senderName}
              </span>
              <span className="text-[10px] text-muted-foreground/60">
                {formatTimestamp(new Date(msg.timestamp))}
              </span>
            </div>
            <p className="mt-0.5 line-clamp-2 text-[13px] text-foreground">{msg.text}</p>
            <div className="mt-1.5 flex items-center gap-2">
              <button
                onClick={() => onJumpTo(msg.id)}
                className="text-[11px] text-primary hover:underline"
              >
                Jump to message
              </button>
              <button
                onClick={() => onUnpin(msg.id)}
                className="text-[11px] text-muted-foreground/60 hover:text-destructive"
              >
                Unpin
              </button>
            </div>
          </div>
        ))}
        {pinnedMessages.length === 0 && (
          <div className="flex h-32 items-center justify-center text-[13px] text-muted-foreground/60">
            No pinned messages
          </div>
        )}
      </div>
    </div>
  );
}

// ─── ChatNestedThread ─────────────────────────────────────────────────────────

interface ThreadedMessage extends ChatMessageData {
  parentId: string | null;
  children: ThreadedMessage[];
  depth: number;
  votes?: number;
  userVote?: "up" | "down" | null;
  isCollapsed?: boolean;
}

interface ChatNestedThreadProps {
  messages: ThreadedMessage[];
  maxDepth?: number;
  onReply?: (parentId: string) => void;
  onVote?: (messageId: string, direction: "up" | "down") => void;
  showVotes?: boolean;
  className?: string;
}

function ChatNestedThread({
  messages,
  maxDepth = 5,
  onReply,
  onVote,
  showVotes = false,
  className,
}: ChatNestedThreadProps) {
  return (
    <div className={cn("space-y-1", className)}>
      {messages.map((msg) => (
        <ThreadMessage
          key={msg.id}
          message={msg}
          maxDepth={maxDepth}
          onReply={onReply}
          onVote={onVote}
          showVotes={showVotes}
        />
      ))}
    </div>
  );
}

function ThreadMessage({
  message,
  maxDepth,
  onReply,
  onVote,
  showVotes,
}: {
  message: ThreadedMessage;
  maxDepth: number;
  onReply?: (parentId: string) => void;
  onVote?: (messageId: string, direction: "up" | "down") => void;
  showVotes: boolean;
}) {
  const [collapsed, setCollapsed] = React.useState(message.isCollapsed ?? false);
  const atMaxDepth = message.depth >= maxDepth;

  return (
    <div style={{ paddingLeft: Math.min(message.depth, maxDepth) * 24 }}>
      <div className="group flex items-start gap-2 rounded-lg px-2 py-1.5 transition-colors hover:bg-accent">
        {/* Thread connector line */}
        {message.depth > 0 && <div className="mt-1 h-full w-0.5 shrink-0 bg-border" />}

        {/* Vote buttons */}
        {showVotes && (
          <div className="flex shrink-0 flex-col items-center gap-0.5">
            <button
              onClick={() => onVote?.(message.id, "up")}
              className={cn(
                "size-5 rounded text-muted-foreground/60 hover:text-primary",
                message.userVote === "up" && "text-primary"
              )}
            >
              <ArrowUp className="size-3.5 mx-auto" />
            </button>
            <span className="text-[11px] font-semibold tabular-nums text-muted-foreground">
              {message.votes ?? 0}
            </span>
            <button
              onClick={() => onVote?.(message.id, "down")}
              className={cn(
                "size-5 rounded text-muted-foreground/60 hover:text-destructive",
                message.userVote === "down" && "text-destructive"
              )}
            >
              <ArrowDown className="size-3.5 mx-auto" />
            </button>
          </div>
        )}

        {/* Content */}
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="text-[13px] font-semibold text-foreground">{message.senderName}</span>
            <span className="text-[11px] text-muted-foreground/60">
              {formatTimestamp(new Date(message.timestamp))}
            </span>
          </div>
          <p className="text-[14px] leading-relaxed text-foreground">{message.text}</p>
          <div className="mt-1 flex items-center gap-3">
            {!atMaxDepth && (
              <button
                onClick={() => onReply?.(message.id)}
                className="text-[11px] font-medium text-muted-foreground hover:text-primary"
              >
                Reply
              </button>
            )}
            {message.children.length > 0 && (
              <button
                onClick={() => setCollapsed(!collapsed)}
                className="flex items-center gap-0.5 text-[11px] font-medium text-muted-foreground hover:text-foreground"
              >
                {collapsed ? (
                  <ChevronRight className="size-3" />
                ) : (
                  <ChevronDown className="size-3" />
                )}
                {message.children.length} {message.children.length === 1 ? "reply" : "replies"}
              </button>
            )}
          </div>
        </div>
      </div>

      {/* Children */}
      {!collapsed && message.children.length > 0 && (
        <div className="border-l-2 border-border ml-3">
          {message.children.map((child) => (
            <ThreadMessage
              key={child.id}
              message={child}
              maxDepth={maxDepth}
              onReply={onReply}
              onVote={onVote}
              showVotes={showVotes}
            />
          ))}
        </div>
      )}

      {atMaxDepth && message.children.length > 0 && (
        <button className="ml-6 mt-1 text-[11px] text-primary hover:underline">
          Continue thread →
        </button>
      )}
    </div>
  );
}

// ─── ChatSearch ───────────────────────────────────────────────────────────────

interface SearchResult {
  messageId: string;
  conversationId?: string;
  conversationName?: string;
  senderName: string;
  snippet: string;
  timestamp: Date | number;
}

interface ChatSearchProps {
  onSearch: (query: string) => SearchResult[] | Promise<SearchResult[]>;
  onSelect: (result: SearchResult) => void;
  onClose: () => void;
  className?: string;
}

function ChatSearch({ onSearch, onSelect, onClose, className }: ChatSearchProps) {
  const [query, setQuery] = React.useState("");
  const [results, setResults] = React.useState<SearchResult[]>([]);
  const inputRef = React.useRef<HTMLInputElement>(null);

  React.useEffect(() => {
    inputRef.current?.focus();
  }, []);

  React.useEffect(() => {
    if (!query.trim()) {
      setResults([]);
      return;
    }
    const timeout = setTimeout(async () => {
      const r = await onSearch(query);
      setResults(r);
    }, 200);
    return () => clearTimeout(timeout);
  }, [query, onSearch]);

  React.useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, [onClose]);

  return (
    <div
      className={cn(
        "fixed inset-0 z-50 flex items-start justify-center pt-[15vh] bg-black/50",
        className
      )}
    >
      <div className="w-full max-w-lg overflow-hidden rounded-xl border border-border bg-card shadow-lg">
        {/* Search input */}
        <div className="flex items-center gap-3 border-b border-border px-4 py-3">
          <Search className="size-4 text-muted-foreground/60" />
          <input
            ref={inputRef}
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search messages..."
            className="flex-1 bg-transparent text-[15px] text-foreground placeholder:text-muted-foreground/60 outline-none"
          />
          <kbd className="rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground/60">
            ESC
          </kbd>
        </div>

        {/* Results */}
        <div className="max-h-80 overflow-y-auto">
          {results.map((r) => (
            <button
              key={r.messageId}
              onClick={() => {
                onSelect(r);
                onClose();
              }}
              className="flex w-full flex-col gap-0.5 border-b border-border px-4 py-2.5 text-left transition-colors hover:bg-accent"
            >
              <div className="flex items-center gap-2">
                <span className="text-[13px] font-semibold text-foreground">{r.senderName}</span>
                {r.conversationName && (
                  <span className="text-[11px] text-muted-foreground/60">
                    in {r.conversationName}
                  </span>
                )}
                <span className="ml-auto text-[11px] text-muted-foreground/60">
                  {formatTimestamp(new Date(r.timestamp))}
                </span>
              </div>
              <p className="truncate text-[13px] text-muted-foreground">{r.snippet}</p>
            </button>
          ))}
          {query.trim() && results.length === 0 && (
            <div className="flex h-20 items-center justify-center text-[13px] text-muted-foreground/60">
              No results found
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Exports ──────────────────────────────────────────────────────────────────

export {
  ChatForwardDialog,
  ChatEditComposer,
  ChatDeletedMessage,
  ChatPinnedPanel,
  ChatNestedThread,
  ChatSearch,
};
export type {
  Conversation,
  ChatForwardDialogProps,
  ChatEditComposerProps,
  ChatDeletedMessageProps,
  ChatPinnedPanelProps,
  ThreadedMessage,
  ChatNestedThreadProps,
  SearchResult,
  ChatSearchProps,
};
