import { useEffect, useState } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Inbox, Plus, MessageSquare, Trash2, ChevronDown, ChevronRight, RotateCcw, Menu, Code } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api/client';
import type { Project as ProjectType, Session } from '@/api/types';
import { EmptyState } from '@/components/EmptyState';
import { Button } from '@/components/ui/button';
import { sessionEvents } from '@/hooks/sessionEvents';
import { useSessions } from '@/hooks/useSessions';
import { isCoderSessionName } from '@/lib/coder-session';
import { useSidebarDrawer } from '@/hooks/useSidebarDrawer';
import { useViewport } from '@/hooks/useViewport';

export function Project() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { sessions, create, remove } = useSessions(id);
  const [project, setProject] = useState<ProjectType | null>(null);
  const [creating, setCreating] = useState(false);
  const [archivedSessions, setArchivedSessions] = useState<Session[] | null>(null);
  const [showArchived, setShowArchived] = useState(false);
  const { setOpen: setDrawerOpen } = useSidebarDrawer();
  const { isMobile } = useViewport();

  useEffect(() => {
    if (!id) return;
    api.projects
      .list()
      .then((list) => setProject(list.find((p) => p.id === id) ?? null))
      .catch(() => {});
  }, [id]);

  useEffect(() => {
    if (!id) return;
    api.sessions.listForProject(id, 'archived')
      .then(setArchivedSessions)
      .catch(() => {});
  }, [id]);

  useEffect(() => {
    return sessionEvents.subscribe((event) => {
      if (event.type === 'session_archived' && event.project_id === id) {
        setArchivedSessions((prev) => {
          if (!prev) return prev;
          if (prev.some((s) => s.id === event.session_id)) return prev;
          const session = sessions?.find((s) => s.id === event.session_id);
          if (!session) return prev;
          return [{ ...session, status: 'archived' as const }, ...prev];
        });
      }
      if (event.type === 'session_deleted' && event.project_id === id) {
        setArchivedSessions((prev) =>
          prev ? prev.filter((s) => s.id !== event.session_id) : prev
        );
      }
    });
  }, [id, sessions]);

  async function handleNew() {
    if (!id || creating) return;
    setCreating(true);
    try {
      const s = await create({});
      // Server publishes session_created via WS; let useUserEvents deliver it.
      navigate(`/session/${s.id}`);
    } finally {
      setCreating(false);
    }
  }

  async function handleUnarchive(sessionId: string) {
    try {
      await api.sessions.unarchive(sessionId);
      setArchivedSessions((prev) =>
        prev ? prev.filter((s) => s.id !== sessionId) : prev
      );
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'failed to unarchive');
    }
  }

  return (
    <div className="flex-1 flex flex-col">
      <header
        className="border-b px-3 sm:px-6 py-2 sm:py-3 flex items-center justify-between gap-2"
        style={{ paddingTop: 'max(0.5rem, env(safe-area-inset-top))' }}
      >
        <div className="flex items-center gap-2 min-w-0">
          {isMobile && (
            <button
              type="button"
              onClick={() => setDrawerOpen(true)}
              className="inline-flex items-center justify-center -ml-1 min-w-[44px] min-h-[44px] rounded text-muted-foreground hover:bg-muted hover:text-foreground shrink-0"
              aria-label="Open sidebar"
            >
              <Menu className="size-5" />
            </button>
          )}
          <div className="min-w-0">
            <h1 className="text-base sm:text-lg font-semibold tracking-tight truncate">
              {project?.name ?? '…'}
            </h1>
            <div className="text-xs text-muted-foreground font-mono truncate hidden sm:block">
              {project?.path}
            </div>
          </div>
        </div>
        <Button onClick={handleNew} disabled={creating} className="shrink-0" aria-label="New session">
          <Plus />
          <span className="hidden sm:inline">New session</span>
        </Button>
      </header>

      <div className="flex-1 overflow-y-auto px-6 py-4 space-y-6">
        {sessions === null && (
          <div className="text-sm text-muted-foreground">Loading…</div>
        )}
        {sessions && sessions.length === 0 && (
          <EmptyState
            icon={<Inbox size={40} strokeWidth={1.5} />}
            title="No sessions"
            description="Start a new chat session to begin working"
          />
        )}
        {sessions && sessions.length > 0 && (
          <ul className="divide-y rounded-md border">
            {sessions.map((s) => (
              <li key={s.id} className="flex items-center justify-between px-3 py-2 hover:bg-muted/50">
                <Link to={`/session/${s.id}`} className="flex-1 flex items-center gap-2 min-w-0">
                  {isCoderSessionName(s.name) ? (
                    <Code className="size-3.5 opacity-70 shrink-0" />
                  ) : (
                    <MessageSquare className="size-3.5 opacity-70 shrink-0" />
                  )}
                  <span className="truncate text-sm">{s.name}</span>
                  <span className="text-xs text-muted-foreground font-mono ml-2 shrink-0">
                    {s.model}
                  </span>
                </Link>
                <Button
                  variant="ghost"
                  size="icon-sm"
                  aria-label="Delete session"
                  onClick={async () => {
                    try {
                      await remove(s.id);
                      // Server publishes session_deleted via WS.
                    } catch (err) {
                      toast.error(
                        err instanceof Error ? err.message : 'failed to delete session'
                      );
                    }
                  }}
                >
                  <Trash2 />
                </Button>
              </li>
            ))}
          </ul>
        )}

        {/* Archived sessions */}
        {archivedSessions && archivedSessions.length > 0 && (
          <div>
            <button
              type="button"
              onClick={() => setShowArchived(!showArchived)}
              className="flex items-center gap-1 text-xs font-medium text-muted-foreground mb-2 hover:text-foreground"
            >
              {showArchived ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
              Closed sessions ({archivedSessions.length})
            </button>
            {showArchived && (
              <ul className="divide-y rounded-md border">
                {archivedSessions.map((s) => (
                  <li key={s.id} className="flex items-center justify-between px-3 py-2 hover:bg-muted/50">
                    <div className="flex-1 flex items-center gap-2 min-w-0">
                      <MessageSquare className="size-3.5 opacity-40 shrink-0" />
                      <span className="truncate text-sm text-muted-foreground">{s.name}</span>
                    </div>
                    <div className="flex items-center gap-1">
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        aria-label="Reopen session"
                        onClick={() => void handleUnarchive(s.id)}
                      >
                        <RotateCcw size={14} />
                      </Button>
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        aria-label="Delete session permanently"
                        onClick={async () => {
                          try {
                            await api.sessions.remove(s.id);
                            setArchivedSessions((prev) =>
                              prev ? prev.filter((a) => a.id !== s.id) : prev
                            );
                          } catch (err) {
                            toast.error(
                              err instanceof Error ? err.message : 'failed to delete'
                            );
                          }
                        }}
                      >
                        <Trash2 />
                      </Button>
                    </div>
                  </li>
                ))}
              </ul>
            )}
          </div>
        )}
      </div>
    </div>
  );
}
