"use client";

import { useState, useMemo, useEffect } from "react";
import type { ActivityEvent, ActivityFilterCategory } from "@/lib/activity";
import { getEventCategory, ACTIVITY_PAGE_SIZE } from "@/lib/activity";
import { ActivityItem } from "./ActivityItem";

interface Props {
  events: ActivityEvent[];
  isOpen: boolean;
  onClose: () => void;
  onNodeClick: (nodeId: string) => void;
  onHandleClick?: (handle: string) => void;
}

const FILTER_CATEGORIES: {
  key: ActivityFilterCategory;
  label: string;
  icon: string;
}[] = [
  { key: "issues", label: "Issues", icon: "circle" },
  { key: "deps", label: "Deps", icon: "link" },
  { key: "comments", label: "Comments", icon: "chat" },
  { key: "claims", label: "Claims", icon: "user" },
  { key: "likes", label: "Likes", icon: "heart" },
];

// ============================================================================
// Time grouping helpers
// ============================================================================

function getTimeGroup(time: number): string {
  const now = Date.now();
  const diff = now - time;
  const hours = diff / (1000 * 60 * 60);
  const days = diff / (1000 * 60 * 60 * 24);

  if (hours < 1) return "Just now";
  if (hours < 24) return "Today";
  if (days < 2) return "Yesterday";
  if (days < 7) return "This week";
  if (days < 30) return "This month";
  return "Older";
}

function groupEventsByTime(events: ActivityEvent[]): { label: string; events: ActivityEvent[] }[] {
  const groups: Map<string, ActivityEvent[]> = new Map();
  const order: string[] = [];

  for (const event of events) {
    const label = getTimeGroup(event.time);
    if (!groups.has(label)) {
      groups.set(label, []);
      order.push(label);
    }
    groups.get(label)!.push(event);
  }

  return order.map((label) => ({ label, events: groups.get(label)! }));
}

/**
 * Full slide-in sidebar panel for the activity feed.
 * Includes search bar, filter chips, and time-grouped events.
 * Same pattern as AllCommentsPanel / NodeDetail.
 */
export function ActivityPanel({
  events,
  isOpen,
  onClose,
  onNodeClick,
  onHandleClick,
}: Props) {
  const [search, setSearch] = useState("");
  const [activeFilters, setActiveFilters] = useState<Set<ActivityFilterCategory>>(
    new Set(FILTER_CATEGORIES.map((c) => c.key))
  );
  const [visibleCount, setVisibleCount] = useState(ACTIVITY_PAGE_SIZE);

  useEffect(() => {
    setVisibleCount(ACTIVITY_PAGE_SIZE);
  }, [events, activeFilters, search]);

  const toggleFilter = (category: ActivityFilterCategory) => {
    setActiveFilters((prev) => {
      const next = new Set(prev);
      if (next.has(category)) {
        // Don't allow deactivating all filters
        if (next.size > 1) next.delete(category);
      } else {
        next.add(category);
      }
      return next;
    });
  };

  const filteredEvents = useMemo(() => {
    let filtered = events;

    // Apply category filters
    filtered = filtered.filter((e) =>
      activeFilters.has(getEventCategory(e.type))
    );

    // Apply text search
    if (search.trim()) {
      const q = search.trim().toLowerCase();
      filtered = filtered.filter(
        (e) =>
          e.nodeId.toLowerCase().includes(q) ||
          (e.nodeTitle && e.nodeTitle.toLowerCase().includes(q)) ||
          (e.actor?.handle && e.actor.handle.toLowerCase().includes(q)) ||
          (e.detail && e.detail.toLowerCase().includes(q))
      );
    }

    return filtered;
  }, [events, activeFilters, search]);

  const groupedEvents = useMemo(
    () => groupEventsByTime(filteredEvents),
    [filteredEvents]
  );

  const visibleEvents = useMemo(
    () => filteredEvents.slice(0, visibleCount),
    [filteredEvents, visibleCount]
  );
  const hasMore = filteredEvents.length > visibleCount;
  const visibleGroupedEvents = useMemo(
    () => groupEventsByTime(visibleEvents),
    [visibleEvents]
  );

  const allActive = activeFilters.size === FILTER_CATEGORIES.length;

  return (
    <>
      {/* Desktop sidebar */}
      <aside
        className={`hidden md:flex absolute top-0 right-0 h-full w-[360px] bg-white dark:bg-zinc-900 border-l border-zinc-200 dark:border-zinc-700 flex-col shadow-xl z-30 transform transition-transform duration-300 ease-out ${
          isOpen ? "translate-x-0" : "translate-x-full"
        }`}
      >
        {/* Header */}
        <div className="shrink-0 px-5 py-3 border-b border-zinc-100 dark:border-zinc-800 flex items-center justify-between">
          <div className="flex items-center gap-2">
            <h2 className="text-xs font-semibold text-zinc-400 uppercase tracking-wider">
              Activity
            </h2>
            {events.length > 0 && (
              <span className="px-1.5 py-0.5 bg-emerald-50 dark:bg-emerald-950 text-emerald-600 dark:text-emerald-400 rounded-full text-[10px] font-medium">
                {events.length}
              </span>
            )}
          </div>
          <button
            onClick={onClose}
            className="p-1 text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors rounded-full hover:bg-zinc-100 dark:hover:bg-zinc-800"
          >
            <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={1.5}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Search */}
        <div className="px-4 pt-3 pb-2 shrink-0">
          <div className="flex items-center bg-zinc-50/80 dark:bg-zinc-800/80 rounded-full border border-zinc-200/60 dark:border-zinc-700/60 overflow-hidden">
            <div className="pl-3 pr-1 text-zinc-400 dark:text-zinc-500">
              <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
              </svg>
            </div>
            <input
              type="text"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder="Search activity..."
              className="flex-1 px-2 py-2 text-xs text-zinc-800 dark:text-zinc-200 bg-transparent outline-none placeholder:text-zinc-400 dark:placeholder:text-zinc-500"
            />
            {search && (
              <button
                onClick={() => setSearch("")}
                className="pr-3 text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300"
              >
                <svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            )}
          </div>
        </div>

        {/* Filter chips */}
        <div className="flex flex-wrap gap-1.5 px-4 pb-3 shrink-0">
          {FILTER_CATEGORIES.map((cat) => {
            const isActive = activeFilters.has(cat.key);
            return (
              <button
                key={cat.key}
                onClick={() => toggleFilter(cat.key)}
                className={`px-2.5 py-1 text-[11px] font-medium rounded-full border transition-all ${
                  isActive
                    ? "bg-emerald-50 dark:bg-emerald-950 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800 shadow-sm"
                    : "bg-white dark:bg-zinc-900 text-zinc-400 dark:text-zinc-500 border-zinc-200 dark:border-zinc-700 hover:text-zinc-600 dark:hover:text-zinc-300 hover:border-zinc-300 dark:hover:border-zinc-600"
                }`}
              >
                {cat.label}
              </button>
            );
          })}
        </div>

        {/* Event list with time groups */}
        <div className="flex-1 overflow-y-auto custom-scrollbar border-t border-zinc-100 dark:border-zinc-800">
          {filteredEvents.length === 0 ? (
            <div className="flex flex-col items-center justify-center py-12 text-center">
              <svg
                className="w-8 h-8 text-zinc-200 dark:text-zinc-700 mb-3"
                fill="none"
                viewBox="0 0 24 24"
                strokeWidth={1.5}
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z"
                />
              </svg>
              <p className="text-xs text-zinc-400 dark:text-zinc-500">
                {search.trim()
                  ? "No activity matching your search"
                  : "No activity yet"}
              </p>
              {search.trim() && (
                <button
                  onClick={() => setSearch("")}
                  className="text-[11px] text-emerald-600 dark:text-emerald-400 hover:text-emerald-700 dark:hover:text-emerald-300 mt-1.5"
                >
                  Clear search
                </button>
              )}
            </div>
          ) : (
            <>
              {visibleGroupedEvents.map((group) => (
                <div key={group.label}>
                  {/* Time group header */}
                  <div className="sticky top-0 z-[1] px-4 py-1.5 bg-zinc-50/95 dark:bg-zinc-800/95 backdrop-blur-sm border-b border-zinc-100/60 dark:border-zinc-700/60">
                    <span className="text-[10px] font-semibold text-zinc-400 uppercase tracking-wider">
                      {group.label}
                    </span>
                  </div>
                  {/* Events in this group */}
                  <div className="divide-y divide-zinc-50 dark:divide-zinc-800">
                    {group.events.map((event) => (
                      <ActivityItem
                        key={event.id}
                        event={event}
                        variant="full"
                        onNodeClick={onNodeClick}
                        onHandleClick={onHandleClick}
                      />
                    ))}
                  </div>
                </div>
              ))}
              {hasMore && (
                <div className="flex justify-center py-3 border-t border-zinc-100/60 dark:border-zinc-700/60">
                  <button
                    onClick={() => setVisibleCount((prev) => prev + ACTIVITY_PAGE_SIZE)}
                    className="text-[11px] text-emerald-600 dark:text-emerald-400 hover:text-emerald-700 dark:hover:text-emerald-300 font-medium px-3 py-1.5 rounded-full hover:bg-emerald-50 dark:hover:bg-emerald-950 transition-colors"
                  >
                    Show {Math.min(ACTIVITY_PAGE_SIZE, filteredEvents.length - visibleCount)} more events
                  </button>
                </div>
              )}
            </>
          )}
        </div>

        {/* Footer stats */}
        <div className="shrink-0 px-5 py-2.5 border-t border-zinc-100 dark:border-zinc-800 bg-zinc-50/50 dark:bg-zinc-800/50">
          <div className="text-[10px] text-zinc-400 dark:text-zinc-500">
            {hasMore
              ? `${visibleCount} of ${filteredEvents.length} events`
              : `${filteredEvents.length} event${filteredEvents.length !== 1 ? "s" : ""}`}
            {!allActive && ` (filtered)`}
            {search.trim() && ` matching "${search.trim()}"`}
          </div>
        </div>
      </aside>

      {/* Mobile drawer */}
      <div
        className={`md:hidden fixed inset-x-0 bottom-0 z-20 transition-transform duration-300 ease-out ${
          isOpen ? "translate-y-0" : "translate-y-full"
        }`}
      >
        <div className="bg-white dark:bg-zinc-900 rounded-t-2xl shadow-xl border-t border-zinc-200 dark:border-zinc-700 max-h-[60vh] flex flex-col">
          {/* Drag handle */}
          <div className="flex justify-center pt-3 pb-1">
            <div className="w-8 h-1 bg-zinc-300 dark:bg-zinc-600 rounded-full" />
          </div>

          {/* Header */}
          <div className="flex items-center justify-between px-5 py-2">
            <div className="flex items-center gap-2">
              <h2 className="text-sm font-semibold text-zinc-900 dark:text-zinc-100">Activity</h2>
              {events.length > 0 && (
                <span className="px-1.5 py-0.5 bg-emerald-50 dark:bg-emerald-950 text-emerald-600 dark:text-emerald-400 rounded-full text-[10px] font-medium">
                  {events.length}
                </span>
              )}
            </div>
            <button
              onClick={onClose}
              className="p-1 text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300"
            >
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={1.5}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          {/* Filter chips */}
          <div className="flex flex-wrap gap-1.5 px-5 pb-3">
            {FILTER_CATEGORIES.map((cat) => (
              <button
                key={cat.key}
                onClick={() => toggleFilter(cat.key)}
                className={`px-2.5 py-1 text-[11px] font-medium rounded-full border transition-colors ${
                  activeFilters.has(cat.key)
                    ? "bg-emerald-50 dark:bg-emerald-950 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800"
                    : "bg-white dark:bg-zinc-900 text-zinc-400 dark:text-zinc-500 border-zinc-200 dark:border-zinc-700"
                }`}
              >
                {cat.label}
              </button>
            ))}
          </div>

          {/* Event list */}
          <div className="flex-1 overflow-y-auto custom-scrollbar">
            {filteredEvents.length === 0 ? (
              <div className="py-8 text-center text-xs text-zinc-400 dark:text-zinc-500">
                No activity matching filters
              </div>
            ) : (
              <>
                {visibleGroupedEvents.map((group) => (
                  <div key={group.label}>
                    <div className="sticky top-0 z-[1] px-5 py-1.5 bg-zinc-50/95 dark:bg-zinc-800/95 backdrop-blur-sm border-b border-zinc-100/60 dark:border-zinc-700/60">
                      <span className="text-[10px] font-semibold text-zinc-400 uppercase tracking-wider">
                        {group.label}
                      </span>
                    </div>
                    <div className="divide-y divide-zinc-50 dark:divide-zinc-800">
                      {group.events.map((event) => (
                        <ActivityItem
                          key={event.id}
                          event={event}
                          variant="full"
                          onNodeClick={onNodeClick}
                          onHandleClick={onHandleClick}
                        />
                      ))}
                    </div>
                  </div>
                ))}
                {hasMore && (
                  <div className="flex justify-center py-3 border-t border-zinc-100/60 dark:border-zinc-700/60">
                    <button
                      onClick={() => setVisibleCount((prev) => prev + ACTIVITY_PAGE_SIZE)}
                      className="text-[11px] text-emerald-600 dark:text-emerald-400 hover:text-emerald-700 dark:hover:text-emerald-300 font-medium px-3 py-1.5 rounded-full hover:bg-emerald-50 dark:hover:bg-emerald-950 transition-colors"
                    >
                      Show {Math.min(ACTIVITY_PAGE_SIZE, filteredEvents.length - visibleCount)} more events
                    </button>
                  </div>
                )}
              </>
            )}
          </div>
        </div>
      </div>
    </>
  );
}
