'use client';

import { useState, useMemo } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Pin, X, Loader2, Search, Info, Link, BookMarked, Archive } from 'lucide-react';
import { pinList, pinRemove, type RoomPinResponse, type RoomMemberResponse } from '@/client';
import { toast } from 'sonner';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { getSenderDisplayName } from './sender';
import { formatMessageTime } from './shared/formatters';
import { cn } from '@/lib/utils';

// ── Category types ────────────────────────────────────────────────────────────

export type PinCategory = 'all' | 'info' | 'resources' | 'rules' | 'archive';

interface CategorizedPin extends RoomPinResponse {
  category: PinCategory;
}

const CATEGORY_META: Record<Exclude<PinCategory, 'all'>, { label: string; Icon: React.ComponentType<{ className?: string }>; color: string }> = {
  info: { label: 'Info', Icon: Info, color: 'text-blue-500' },
  resources: { label: 'Resources', Icon: Link, color: 'text-green-500' },
  rules: { label: 'Rules', Icon: BookMarked, color: 'text-amber-500' },
  archive: { label: 'Archive', Icon: Archive, color: 'text-muted-foreground' },
};

// ── Smart categorization ─────────────────────────────────────────────────────

function categorizePin(pin: RoomPinResponse): PinCategory {
  const content = (pin as unknown as { content?: string }).content ?? '';
  const lower = content.toLowerCase();

  if (
    /https?:\/\/|github\.com|bitbucket\.org|gitlab\.com|docs\.|readme|wiki|spec|rfc|md\b/i.test(lower) ||
    /@[a-z]+(?:\/[a-z]+){0,2}\b/.test(content) // repo/project mentions
  ) {
    return 'resources';
  }
  if (
    /\b(do not|must not|please remember|always|never|rule|guideline|policy|forbidden|required|ensure that|make sure)\b/i.test(lower)
  ) {
    return 'rules';
  }

  // Archive pins older than 30 days
  const age = Date.now() - new Date(pin.pinned_at).getTime();
  if (age > 30 * 24 * 60 * 60 * 1000) {
    return 'archive';
  }
  return 'info';
}

// ── Props ─────────────────────────────────────────────────────────────────────

interface RoomPinPanelProps {
  roomId: string;
  messages: Array<{
    id: string;
    content: string;
    sender_id: string;
    sender_type: string;
    send_at: string;
  }>;
  members: RoomMemberResponse[];
  onClose: () => void;
  onJumpToMessage: (messageId: string) => void;
}

export function RoomPinPanel({ roomId, messages, members, onClose, onJumpToMessage }: RoomPinPanelProps) {
  const queryClient = useQueryClient();
  const [activeCategory, setActiveCategory] = useState<PinCategory>('all');
  const [search, setSearch] = useState('');

  const { data: pins, isLoading } = useQuery({
    queryKey: ['roomPins', roomId],
    queryFn: async () => {
      const resp = await pinList({ path: { room_id: roomId } });
      const raw = resp.data?.data ?? ([] as RoomPinResponse[]);
      // Attach content from local messages for categorization
      return raw.map((p) => ({
        ...p,
        content: messages.find((m) => m.id === p.message)?.content ?? '',
      })) as Array<RoomPinResponse & { content: string }>;
    },
    staleTime: 30_000,
  });

  const unpinMutation = useMutation({
    mutationFn: async (messageId: string) => {
      await pinRemove({ path: { room_id: roomId, message_id: messageId } });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['roomPins', roomId] });
      toast.success('Message unpinned');
    },
    onError: () => {
      toast.error('Failed to unpin message');
    },
  });

  const messageMap = useMemo(() => new Map(messages.map((m) => [m.id, m])), [messages]);

  const categorizedPins = useMemo<CategorizedPin[]>(() => {
    if (!pins) return [];
    return pins.map((p) => ({
      ...p,
      category: categorizePin(p as unknown as RoomPinResponse),
    }));
  }, [pins]);

  const filteredPins = useMemo(() => {
    return categorizedPins.filter((p) => {
      const matchesCategory = activeCategory === 'all' || p.category === activeCategory;
      const matchesSearch =
        !search ||
        (messageMap.get(p.message)?.content ?? '').toLowerCase().includes(search.toLowerCase());
      return matchesCategory && matchesSearch;
    });
  }, [categorizedPins, activeCategory, search, messageMap]);

  const countByCategory = useMemo(() => {
    const counts: Record<PinCategory, number> = { all: categorizedPins.length, info: 0, resources: 0, rules: 0, archive: 0 };
    for (const p of categorizedPins) {
      if (p.category !== 'all') counts[p.category]++;
    }
    return counts;
  }, [categorizedPins]);

  const categories: PinCategory[] = ['all', 'info', 'resources', 'rules', 'archive'];

  return (
    <aside
      className="flex flex-col border-l z-20 animate-in slide-in-from-right duration-200"
      style={{
        width: 380,
        borderColor: 'var(--room-border)',
        background: 'var(--room-bg)',
        top: '48px',
        bottom: 0,
        right: 0,
        position: 'absolute',
      }}
    >
      {/* Header */}
      <div
        className="flex items-center justify-between px-4 py-3 border-b shrink-0"
        style={{ borderColor: 'var(--room-border)' }}
      >
        <div className="flex items-center gap-2">
          <Pin className="h-4 w-4" style={{ color: 'var(--room-accent)' }} />
          <span className="text-sm font-semibold" style={{ color: 'var(--room-text)' }}>
            Pinned
          </span>
          {pins && (
            <span
              className="text-[11px] px-1.5 py-0.5 rounded-full"
              style={{ background: 'var(--room-channel-active)', color: 'var(--room-text-muted)' }}
            >
              {pins.length}
            </span>
          )}
        </div>
        <button
          onClick={onClose}
          className="flex h-6 w-6 items-center justify-center rounded-md transition-colors cursor-pointer bg-transparent border-0"
          style={{ color: 'var(--room-text-muted)' }}
        >
          <X className="h-4 w-4" />
        </button>
      </div>

      {/* Search */}
      <div className="px-4 py-2 border-b" style={{ borderColor: 'var(--room-border)' }}>
        <div className="relative">
          <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--room-text-muted)]" />
          <input
            type="text"
            placeholder="Search pins…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="w-full h-7 pl-7 pr-3 rounded text-[12px] bg-transparent border-0 outline-none placeholder:text-[var(--room-text-muted)]"
            style={{ color: 'var(--room-text)', background: 'var(--room-channel-active)' }}
          />
        </div>
      </div>

      {/* Category tabs */}
      <div
        className="flex items-center gap-1 px-4 py-1.5 border-b overflow-x-auto shrink-0"
        style={{ borderColor: 'var(--room-border)' }}
      >
        {categories.map((cat) => {
          const meta = cat === 'all' ? null : CATEGORY_META[cat];
          const count = countByCategory[cat];
          if (cat !== 'all' && count === 0) return null;
          return (
            <button
              key={cat}
              onClick={() => setActiveCategory(cat)}
              className={cn(
                'flex items-center gap-1 px-2 py-1 rounded text-[11px] font-medium whitespace-nowrap transition-colors cursor-pointer border-0 bg-transparent',
                activeCategory === cat
                  ? 'text-[var(--room-accent)]'
                  : 'text-[var(--room-text-muted)] hover:text-[var(--room-text)]',
              )}
            >
              {meta && <meta.Icon className={cn('h-3 w-3', meta.color)} />}
              {cat === 'all' ? 'All' : meta?.label}
              <span
                className="ml-0.5 px-1 rounded-full text-[10px]"
                style={{ background: activeCategory === cat ? 'var(--room-channel-active)' : 'transparent' }}
              >
                {count}
              </span>
            </button>
          );
        })}
      </div>

      {/* Content */}
      <div className="flex-1 overflow-y-auto">
        {isLoading ? (
          <div className="flex items-center justify-center h-24">
            <Loader2 className="h-5 w-5 animate-spin" style={{ color: 'var(--room-text-muted)' }} />
          </div>
        ) : filteredPins.length === 0 ? (
          <div className="flex flex-col items-center justify-center h-32 gap-2">
            <Pin className="h-8 w-8 opacity-30" style={{ color: 'var(--room-text-muted)' }} />
            <p className="text-sm" style={{ color: 'var(--room-text-muted)' }}>
              {search ? 'No matching pins' : 'No pinned messages'}
            </p>
          </div>
        ) : (
          <div className="divide-y" style={{ borderColor: 'var(--room-border)' }}>
            {filteredPins.map((pin) => {
              const localMsg = messageMap.get(pin.message);
              const catMeta = pin.category === 'all' ? null : CATEGORY_META[pin.category];
              return (
                <div
                  key={pin.message}
                  className="group px-4 py-3 hover:bg-[var(--room-channel-active)] transition-colors cursor-pointer"
                  onClick={() => {
                    onJumpToMessage(pin.message);
                    onClose();
                  }}
                >
                  {/* Sender row */}
                  <div className="flex items-center gap-1.5 mb-1">
                    {catMeta && (
                      <catMeta.Icon className={cn('h-3 w-3 shrink-0', catMeta.color)} />
                    )}
                    <Avatar className="h-5 w-5">
                      {(() => {
                        const member = members.find((m) => m.user === pin.pinned_by);
                        return (
                          <>
                            {member?.user_info?.avatar_url ? (
                              <AvatarImage src={member.user_info.avatar_url} className="h-5 w-5" />
                            ) : null}
                            <AvatarFallback className="h-5 w-5 text-[10px]">
                              {(member?.user_info?.username ?? pin.pinned_by).charAt(0).toUpperCase()}
                            </AvatarFallback>
                          </>
                        );
                      })()}
                    </Avatar>
                    <span className="text-xs font-medium" style={{ color: 'var(--room-text)' }}>
                      {(() => {
                        const member = members.find((m) => m.user === pin.pinned_by);
                        return member?.user_info?.username ?? pin.pinned_by;
                      })()}
                    </span>
                    <span className="text-[11px]" style={{ color: 'var(--room-text-muted)' }}>
                      {formatMessageTime(pin.pinned_at).split(':').slice(0, 2).join(':')}
                    </span>
                    <button
                      onClick={(e) => {
                        e.stopPropagation();
                        unpinMutation.mutate(pin.message);
                      }}
                      className="ml-auto opacity-0 group-hover:opacity-100 transition-opacity flex h-5 w-5 items-center justify-center rounded text-[var(--room-text-muted)] hover:text-red-400 cursor-pointer bg-transparent border-0"
                      title="Unpin"
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </div>

                  {/* Message preview */}
                  <p
                    className="text-[13px] line-clamp-2 pl-5"
                    style={{ color: 'var(--room-text-secondary)' }}
                  >
                    {localMsg
                      ? localMsg.content.length > 120
                        ? localMsg.content.slice(0, 120) + '…'
                        : localMsg.content
                      : `[Message #${pin.message}]`}
                  </p>

                  {/* Original sender */}
                  {localMsg && (
                    <div className="mt-0.5 pl-5">
                      <span className="text-[11px]" style={{ color: 'var(--room-text-muted)' }}>
                        {getSenderDisplayName(localMsg as Parameters<typeof getSenderDisplayName>[0])} • {formatMessageTime(localMsg.send_at)}
                      </span>
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        )}
      </div>
    </aside>
  );
}
