import { useState, useEffect, useRef, useMemo } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import { toast } from 'sonner';
import { ArrowLeft, Pencil, Plus, Check, X, Trash2, Search } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { useClient } from 'hooks/useClient';
import { useVisibleClaudeModels } from '@/state/useModels';
import { Card } from '@/components/Card';
import type { ChatMessage } from 'widgets/Chat';
import { useClaude } from '@/Screens/Dashboard/Chat/useClaude';
import { EmbeddableChat } from '@/Screens/Dashboard/Chat/EmbeddableChat';
type ResourceSummary = {
  dirName: string;
  name: string;
  description: string;
  scope: 'global' | 'user';
};

type ResourceDetail = ResourceSummary & {
  body: string;
  filePath: string;
  chatSessionId: string | null;
};

type ResourcePageProps = {
  kind: string;
  endpoint: string;
  queryKey: string;
};

type ResourceChatProps = {
  kind: string;
  endpoint: string;
  dirName: string;
  filePath: string;
  resourceDir: string;
  chatSessionId: string | null;
  isNew?: boolean;
  onResponseEnd?: () => void;
};

const ResourceChat = ({
  kind,
  endpoint,
  dirName,
  filePath,
  resourceDir,
  chatSessionId,
  isNew,
  onResponseEnd,
}: ResourceChatProps) => {
  const client = useClient();
  const claudeModels = useVisibleClaudeModels();
  const defaultInput = chatSessionId
    ? undefined
    : isNew
      ? `Help me create the content for this new ${kind} file: ${filePath}`
      : `Help me understand and improve this ${kind} file: ${filePath}`;

  const storage = useMemo(
    () => ({
      load: async () => {
        const data = await client.get<{ sessionId: string | null; messages: ChatMessage[] }>(
          `${endpoint}/${dirName}/chat`,
        );
        return { sessionId: data.sessionId, messages: data.messages ?? [] };
      },
      save: async (sessionId: string, messages: ChatMessage[]) => {
        await client.put(`${endpoint}/${dirName}/chat`, { sessionId, messages });
      },
    }),
    [endpoint, dirName],
  );

  const claude = useClaude(chatSessionId ?? undefined, undefined, {
    replaceUrl: false,
    storage,
    resourceChatDir: resourceDir,
  });

  const onResponseEndRef = useRef(onResponseEnd);
  onResponseEndRef.current = onResponseEnd;

  const wasGenerating = useRef(false);
  useEffect(() => {
    if (wasGenerating.current && !claude.isGenerating) {
      onResponseEndRef.current?.();
    }
    wasGenerating.current = claude.isGenerating;
  }, [claude.isGenerating]);

  return (
    <EmbeddableChat
      chat={claude}
      provider="claude"
      availableModels={claudeModels}
      defaultInput={defaultInput}
      className="h-full"
    />
  );
};

export const ResourcePage = ({ kind, endpoint, queryKey }: ResourcePageProps) => {
  const client = useClient();
  const qc = useQueryClient();
  const [selected, setSelected] = useState<string | null>(null);
  const [editing, setEditing] = useState(false);
  const [isNew, setIsNew] = useState(false);
  const [creating, setCreating] = useState(false);
  const [newName, setNewName] = useState('');
  const [deleteConfirm, setDeleteConfirm] = useState(false);
  const [search, setSearch] = useState('');
  const [showDetail, setShowDetail] = useState(false);
  const newNameRef = useRef<HTMLInputElement | null>(null);

  const { data: items = [] } = useQuery<ResourceSummary[]>({
    queryKey: [queryKey],
    queryFn: () => client.get<ResourceSummary[]>(endpoint),
  });

  useEffect(() => {
    if (items.length > 0 && !selected) {
      setSelected(items[0]!.dirName);
    }
  }, [items, selected]);

  const { data: detail } = useQuery<ResourceDetail>({
    queryKey: [queryKey, selected],
    queryFn: () => client.get<ResourceDetail>(`${endpoint}/${selected}`),
    enabled: !!selected,
  });

  const selectItem = (dirName: string) => {
    setSelected(dirName);
    setShowDetail(true);
    setIsNew(false);
    setEditing(false);
  };

  const handleCreate = async () => {
    const name = newName.trim();
    if (!name) return;
    try {
      const res = await client.post<{ name: string; dirName: string }>(endpoint, { name });
      await qc.invalidateQueries({ queryKey: [queryKey] });
      setCreating(false);
      setNewName('');
      setSelected(res.dirName);
      setShowDetail(true);
      setIsNew(true);
      setEditing(true);
    } catch {
      toast.error(`Failed to create ${kind}`);
    }
  };

  const handleDelete = async () => {
    if (!selected) return;
    try {
      await client.delete(`${endpoint}/${selected}`);
      setDeleteConfirm(false);
      setEditing(false);
      setSelected(null);
      setShowDetail(false);
      await qc.invalidateQueries({ queryKey: [queryKey] });
    } catch {
      toast.error(`Failed to delete ${kind}`);
    }
  };

  const filtered = items.filter(
    (item) =>
      !search ||
      item.name.toLowerCase().includes(search.toLowerCase()) ||
      item.description?.toLowerCase().includes(search.toLowerCase()),
  );

  return (
    <>
      <div className="flex h-full p-2 md:p-4 gap-2 md:gap-4">
        {/* Left panel — list */}
        <Card
          className={`md:w-72 shrink-0 overflow-hidden flex flex-col ${showDetail ? 'hidden md:flex' : 'flex-1 md:flex-none'}`}
        >
          <div className="shrink-0 px-4 py-2 border-b border-duck-dark/10 bg-white/60 flex items-center justify-between">
            <span className="text-sm font-medium text-duck-dark/70">{kind}s</span>
            {!creating && (
              <button
                onClick={() => {
                  setCreating(true);
                  setTimeout(() => newNameRef.current?.focus(), 0);
                }}
                className="p-1 rounded hover:bg-duck-dark/10 cursor-pointer transition-colors"
              >
                <Plus className="h-4 w-4 text-duck-dark/50" />
              </button>
            )}
          </div>
          {creating && (
            <div className="shrink-0 px-3 py-2 border-b border-duck-dark/10 bg-duck-teal/5 flex items-center gap-1.5">
              <input
                ref={newNameRef}
                value={newName}
                onChange={(ev) => setNewName(ev.target.value)}
                onKeyDown={(ev) => {
                  if (ev.key === 'Enter') {
                    ev.preventDefault();
                    handleCreate();
                  }
                  if (ev.key === 'Escape') {
                    setCreating(false);
                    setNewName('');
                  }
                }}
                placeholder={`${kind} name...`}
                className="flex-1 min-w-0 rounded border border-duck-dark/20 bg-white px-2 py-1 text-base md:text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-1 focus:ring-duck-teal/30"
              />
              <button
                onClick={handleCreate}
                disabled={!newName.trim()}
                className="p-1 rounded hover:bg-duck-dark/10 cursor-pointer transition-colors disabled:opacity-30"
              >
                <Check className="h-3.5 w-3.5 text-duck-teal" />
              </button>
              <button
                onClick={() => {
                  setCreating(false);
                  setNewName('');
                }}
                className="p-1 rounded hover:bg-duck-dark/10 cursor-pointer transition-colors"
              >
                <X className="h-3.5 w-3.5 text-duck-dark/50" />
              </button>
            </div>
          )}
          <div className="shrink-0 px-3 py-2 border-b border-duck-dark/10">
            <div className="relative">
              <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-duck-dark/30" />
              <input
                value={search}
                onChange={(ev) => setSearch(ev.target.value)}
                placeholder={`Search ${kind.toLowerCase()}s...`}
                className="w-full rounded border border-duck-dark/15 bg-white/80 pl-7 pr-2 py-1 text-base md:text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-1 focus:ring-duck-teal/30"
              />
            </div>
          </div>
          <div className="overflow-y-auto flex-1">
            {filtered.map((item) => (
              <button
                key={item.dirName}
                onClick={() => selectItem(item.dirName)}
                className={`w-full text-left px-4 py-3 border-b border-duck-dark/5 cursor-pointer transition-colors ${
                  selected === item.dirName ? 'bg-duck-teal/10' : 'hover:bg-duck-dark/5'
                }`}
              >
                <div className="flex items-center gap-2">
                  <span className="text-sm font-medium text-duck-dark truncate">{item.name}</span>
                  <span
                    className={`shrink-0 text-[10px] px-1.5 py-0.5 rounded-full font-medium ${
                      item.scope === 'user' ? 'bg-duck-teal/20 text-duck-teal' : 'bg-duck-dark/10 text-duck-dark/60'
                    }`}
                  >
                    {item.scope}
                  </span>
                </div>
                {item.description && <p className="text-xs text-duck-dark/50 mt-1 line-clamp-2">{item.description}</p>}
              </button>
            ))}
            {items.length === 0 && (
              <p className="text-sm text-duck-dark/40 px-4 py-6 text-center">No {kind.toLowerCase()}s found</p>
            )}
            {items.length > 0 && filtered.length === 0 && (
              <p className="text-sm text-duck-dark/40 px-4 py-6 text-center">No matches</p>
            )}
          </div>
        </Card>

        {/* Right panel — detail + chat */}
        <div className={`flex-1 flex flex-col gap-4 min-h-0 ${showDetail ? 'flex' : 'hidden md:flex'}`}>
          <Card className={`flex-1 overflow-hidden flex flex-col min-h-0 ${editing ? 'hidden md:flex' : ''}`}>
            <div className="shrink-0 px-4 py-2 border-b border-duck-dark/10 bg-white/60 flex items-center gap-2">
              <button
                onClick={() => setShowDetail(false)}
                className="md:hidden p-1 -ml-1 rounded hover:bg-duck-dark/10 cursor-pointer"
              >
                <ArrowLeft className="h-4 w-4 text-duck-dark/60" />
              </button>
              <span className="text-sm font-medium text-duck-dark/70 flex-1">
                {detail?.name ?? `Select a ${kind.toLowerCase()}`}
              </span>
              {detail && (
                <>
                  <button
                    onClick={() => setEditing((e) => !e)}
                    className={`p-1 rounded hover:bg-duck-dark/10 cursor-pointer transition-colors ${editing ? 'bg-duck-teal/10' : ''}`}
                  >
                    <Pencil className={`h-3.5 w-3.5 ${editing ? 'text-duck-teal' : 'text-duck-dark/50'}`} />
                  </button>
                  <button
                    onClick={() => setDeleteConfirm(true)}
                    className="p-1 rounded hover:bg-red-50 cursor-pointer transition-colors"
                  >
                    <Trash2 className="h-3.5 w-3.5 text-duck-dark/50 hover:text-red-500" />
                  </button>
                </>
              )}
            </div>
            <div className="overflow-y-auto flex-1 p-6">
              {detail?.body ? (
                <article className="skill-md">
                  <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
                    {detail.body}
                  </ReactMarkdown>
                </article>
              ) : detail ? (
                <p className="text-sm text-duck-dark/40 text-center mt-12">Empty file</p>
              ) : (
                <p className="text-sm text-duck-dark/40 text-center mt-12">
                  Select a {kind.toLowerCase()} to view its contents
                </p>
              )}
            </div>
          </Card>

          {editing && detail?.filePath && selected && (
            <Card className="flex-1 overflow-hidden flex flex-col min-h-0">
              <div className="shrink-0 px-4 py-1.5 border-b border-duck-dark/10 bg-white/60 flex items-center gap-2">
                <button
                  onClick={() => setEditing(false)}
                  className="md:hidden p-1 -ml-1 rounded hover:bg-duck-dark/10 cursor-pointer"
                >
                  <ArrowLeft className="h-4 w-4 text-duck-dark/60" />
                </button>
                <span className="text-xs font-medium text-duck-dark/50 flex-1">{detail?.name ?? 'Chat'}</span>
                <button
                  onClick={() => setEditing(false)}
                  className="p-1 rounded hover:bg-duck-dark/10 cursor-pointer transition-colors"
                >
                  <X className="h-3.5 w-3.5 text-duck-dark/50" />
                </button>
              </div>
              <ResourceChat
                kind={kind.toLowerCase()}
                key={detail.filePath}
                endpoint={endpoint}
                dirName={selected}
                filePath={detail.filePath}
                resourceDir={detail.filePath.replace(/\/[^/]+$/, '')}
                chatSessionId={detail.chatSessionId}
                isNew={isNew}
                onResponseEnd={() => qc.invalidateQueries({ queryKey: [queryKey, selected] })}
              />
            </Card>
          )}
        </div>
      </div>

      <Dialog open={deleteConfirm} onOpenChange={setDeleteConfirm}>
        <DialogContent className="sm:max-w-md z-[700]">
          <DialogHeader>
            <DialogTitle>Delete {kind}</DialogTitle>
            <DialogDescription>
              Are you sure you want to delete &quot;{detail?.name}&quot;? This action cannot be undone.
            </DialogDescription>
          </DialogHeader>
          <div className="flex justify-end gap-2 mt-2">
            <Button variant="outline" onClick={() => setDeleteConfirm(false)} className="cursor-pointer">
              Cancel
            </Button>
            <Button variant="destructive" onClick={handleDelete} className="cursor-pointer">
              Delete
            </Button>
          </div>
        </DialogContent>
      </Dialog>
    </>
  );
};
