import { useState, useRef, useEffect } from 'react';
import { Sparkles, ArrowUp, Loader2, CheckCircle2 } from 'lucide-react';
import { trpc } from '@/lib/trpc';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { ScrollArea } from '@/components/ui/scroll-area';
import { cn } from '@/lib/utils';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from '@/components/ui/dialog';
import { ChatMarkdown } from '@/components/ai/AIChatPanel';

interface JourneyMessage {
  role: 'user' | 'assistant';
  content: string;
}

/** Parse a JSON string safely — returns null on failure. */
function parseAgentConfig(raw: string): Record<string, unknown> | null {
  try {
    const parsed = JSON.parse(raw);
    return parsed && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : null;
  } catch {
    return null;
  }
}

/** Render a short human-readable summary of an AgentConfig object. */
function AgentConfigSummary({ config }: { config: Record<string, unknown> }) {
  const contentTypes = config.content_types as { id?: string; label?: string }[] | undefined;
  const dataTypes = config.data_types as string[] | undefined;
  const globalRules = config.global_rules as string[] | undefined;

  return (
    <div className="text-xs leading-relaxed space-y-1">
      {dataTypes && dataTypes.length > 0 && (
        <p><span className="font-medium">Extracts:</span> {dataTypes.join(', ')}</p>
      )}
      {contentTypes && contentTypes.length > 0 && (
        <p><span className="font-medium">Content types:</span>{' '}
          {contentTypes.map(ct => ct.label ?? ct.id).join(', ')}
        </p>
      )}
      {globalRules && globalRules.length > 0 && (
        <p><span className="font-medium">Rules:</span> {globalRules.length} global rule{globalRules.length !== 1 ? 's' : ''}</p>
      )}
    </div>
  );
}

export function JourneyDialog({
  agentType,
  agentName,
  currentConfig,
  dataTypes,
  directory,
  onClose,
  onSaved,
}: {
  agentType: 'local' | 'cloud';
  agentName: string;
  currentConfig: Record<string, unknown> | null;
  dataTypes: string[];
  directory?: string;
  onClose: () => void;
  onSaved: (agentConfig: Record<string, unknown>) => void;
}) {
  const startMutation = trpc.agent.journey.start.useMutation();
  const messageMutation = trpc.agent.journey.message.useMutation();

  const [sessionId, setSessionId] = useState<string | null>(null);
  const [messages, setMessages] = useState<JourneyMessage[]>([]);
  const [input, setInput] = useState('');
  const [finalConfig, setFinalConfig] = useState<Record<string, unknown> | null>(currentConfig);
  const [isLoading, setIsLoading] = useState(false);
  const [isDone, setIsDone] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);

  // Map 'local' | 'cloud' to the BE enum format
  const journeyAgentType = agentType === 'local' ? 'local_directory' as const : 'gmail' as const;

  // Start journey on mount
  useEffect(() => {
    setIsLoading(true);
    startMutation.mutate(
      {
        agentType: journeyAgentType,
        dataTypes,
        directory,
        existingConfig: currentConfig ? JSON.stringify(currentConfig) : undefined,
      },
      {
        onSuccess: (res) => {
          if (res.data) {
            setSessionId(res.data.sessionId);
            setMessages([{ role: 'assistant', content: res.data.message }]);
            if (res.data.done && res.data.agentConfig) {
              const parsed = parseAgentConfig(res.data.agentConfig);
              if (parsed) {
                setFinalConfig(parsed);
                setIsDone(true);
              }
            }
          }
          setIsLoading(false);
        },
        onError: () => {
          setMessages([{
            role: 'assistant',
            content: "Hi! I'll help you set up your agent configuration. What kinds of files will this agent process, and what should it extract from them?",
          }]);
          setIsLoading(false);
        },
      },
    );
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  function handleSend() {
    if (!input.trim() || isLoading || isDone) return;
    const userMsg = input.trim();
    setInput('');
    setMessages(prev => [...prev, { role: 'user', content: userMsg }]);
    setIsLoading(true);

    messageMutation.mutate(
      { sessionId: sessionId ?? '', message: userMsg },
      {
        onSuccess: (res) => {
          if (res.data) {
            setMessages(prev => [...prev, { role: 'assistant', content: res.data.message }]);
            if (res.data.done && res.data.agentConfig) {
              const parsed = parseAgentConfig(res.data.agentConfig);
              if (parsed) {
                setFinalConfig(parsed);
                setIsDone(true);
              }
            }
          } else {
            setMessages(prev => [...prev, { role: 'assistant', content: 'Something went wrong. Please try again.' }]);
          }
          setIsLoading(false);
        },
        onError: () => {
          setMessages(prev => [...prev, { role: 'assistant', content: 'Could not reach backend. Check your connection.' }]);
          setIsLoading(false);
        },
      },
    );
  }

  return (
    <Dialog open onOpenChange={onClose}>
      <DialogContent className="max-w-xl flex flex-col h-[600px] p-0 gap-0">
        <DialogHeader className="px-6 pt-5 pb-4 border-b shrink-0">
          <DialogTitle className="flex items-center gap-2">
            <Sparkles className="size-4 text-primary" />
            Configure agent — {agentName}
          </DialogTitle>
          <DialogDescription>
            Describe what this agent should look for — we'll produce a tailored extraction config.
          </DialogDescription>
        </DialogHeader>

        {/* Messages */}
        <ScrollArea className="flex-1 px-6 py-4">
          <div className="flex flex-col gap-3">
            {messages.map((msg, i) => (
              <div
                key={i}
                className={cn(
                  'rounded-2xl px-4 py-2.5 text-sm max-w-[85%]',
                  msg.role === 'user'
                    ? 'ml-auto bg-primary text-primary-foreground'
                    : 'bg-muted text-foreground',
                )}
              >
                {msg.role === 'assistant'
                  ? <ChatMarkdown content={msg.content} />
                  : msg.content}
              </div>
            ))}
            {isLoading && (
              <div className="bg-muted rounded-2xl px-4 py-2.5 text-sm max-w-[85%] flex items-center gap-2 text-muted-foreground">
                <Loader2 className="size-3 animate-spin" />
                Thinking...
              </div>
            )}
            <div ref={messagesEndRef} />
          </div>
        </ScrollArea>

        {/* Config preview */}
        {finalConfig && (
          <div className="mx-6 mb-3 rounded-xl bg-muted/50 border px-4 py-3">
            <p className="text-xs font-medium text-muted-foreground mb-1.5">Extraction config ready</p>
            <AgentConfigSummary config={finalConfig} />
          </div>
        )}

        {/* Input */}
        <div className="px-4 pb-4 shrink-0 border-t pt-3">
          {isDone ? (
            <div className="flex items-center gap-2 px-3.5 py-2.5 rounded-xl bg-primary/5 border border-primary/20">
              <CheckCircle2 className="size-4 text-primary shrink-0" />
              <p className="text-sm text-muted-foreground">Config ready — click &ldquo;Save &amp; apply&rdquo; below.</p>
            </div>
          ) : (
            <div className="flex gap-2">
              <Input
                placeholder="Type your answer..."
                value={input}
                onChange={(e) => setInput(e.target.value)}
                onKeyDown={(e) => e.key === 'Enter' && !e.shiftKey && handleSend()}
                disabled={isLoading}
              />
              <Button size="icon" onClick={handleSend} disabled={isLoading || !input.trim()}>
                <ArrowUp className="size-4" />
              </Button>
            </div>
          )}
        </div>

        {/* Footer */}
        <DialogFooter className="px-6 pb-5 gap-2 shrink-0">
          <Button variant="outline" onClick={onClose}>Cancel</Button>
          <Button
            onClick={() => finalConfig && onSaved(finalConfig)}
            disabled={!finalConfig}
          >
            Save &amp; apply
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
