'use client';

import { useState } from 'react';
import { Ban, Send } from 'lucide-react';
import { toast } from 'sonner';

import type { Doc } from '@spoon/backend/convex/_generated/dataModel.js';
import { Badge, Button, Textarea } from '@spoon/ui';

export const AgentThread = ({
  jobId,
  messages,
  events,
  interactions,
  disabled,
  agentTurnActive,
}: {
  jobId: string;
  messages: Doc<'agentJobMessages'>[];
  events: Doc<'agentJobEvents'>[];
  interactions: Doc<'agentInteractionRequests'>[];
  disabled: boolean;
  agentTurnActive: boolean;
}) => {
  const [content, setContent] = useState('');
  const [sending, setSending] = useState(false);
  const [replying, setReplying] = useState<string>();

  const send = async () => {
    if (!content.trim()) return;
    setSending(true);
    try {
      const response = await fetch(`/api/agent-jobs/${jobId}/message`, {
        method: 'POST',
        body: JSON.stringify({ content }),
      });
      if (!response.ok) throw new Error(await response.text());
      setContent('');
    } catch (error) {
      console.error(error);
      toast.error('Could not send message.');
    } finally {
      setSending(false);
    }
  };

  const abort = async () => {
    try {
      const response = await fetch(`/api/agent-jobs/${jobId}/agent/abort`, {
        method: 'POST',
      });
      if (!response.ok) throw new Error(await response.text());
      toast.success('Agent turn aborted.');
    } catch (error) {
      console.error(error);
      toast.error('Could not abort agent.');
    }
  };

  const reply = async (
    interaction: Doc<'agentInteractionRequests'>,
    responseValue: string,
  ) => {
    setReplying(interaction._id);
    try {
      const response = await fetch(
        `/api/agent-jobs/${jobId}/interactions/${interaction._id}/reply`,
        {
          method: 'POST',
          body: JSON.stringify({
            externalRequestId: interaction.externalRequestId,
            response: responseValue,
          }),
        },
      );
      if (!response.ok) throw new Error(await response.text());
      toast.success('Response sent.');
    } catch (error) {
      console.error(error);
      toast.error('Could not answer interaction.');
    } finally {
      setReplying(undefined);
    }
  };

  return (
    <div className='flex h-full min-h-[520px] flex-col'>
      <div className='border-border flex items-start justify-between gap-3 border-b p-3'>
        <div>
          <h2 className='text-sm font-semibold'>Agent thread</h2>
          <p className='text-muted-foreground text-xs'>
            Messages, tool activity, and requests persist with this workspace.
          </p>
        </div>
        <Button
          type='button'
          variant='outline'
          size='sm'
          disabled={disabled || !agentTurnActive}
          onClick={abort}
        >
          <Ban className='size-3' />
          Abort
        </Button>
      </div>
      <div className='min-h-0 flex-1 space-y-3 overflow-auto p-3'>
        {interactions.map((interaction) => (
          <article
            key={interaction._id}
            className='border-primary/40 bg-primary/5 rounded-md border p-3 text-sm'
          >
            <div className='mb-2 flex items-center justify-between gap-2'>
              <span className='font-medium'>{interaction.title}</span>
              <Badge variant='outline' className='capitalize'>
                {interaction.status}
              </Badge>
            </div>
            <p className='text-sm whitespace-pre-wrap'>{interaction.body}</p>
            {interaction.status === 'pending' ? (
              <div className='mt-3 flex gap-2'>
                <Button
                  type='button'
                  size='sm'
                  disabled={replying === interaction._id}
                  onClick={() => void reply(interaction, 'once')}
                >
                  Approve
                </Button>
                <Button
                  type='button'
                  size='sm'
                  variant='outline'
                  disabled={replying === interaction._id}
                  onClick={() => void reply(interaction, 'reject')}
                >
                  Reject
                </Button>
              </div>
            ) : null}
          </article>
        ))}
        {messages.map((message) => (
          <article
            key={message._id}
            className={
              message.role === 'user'
                ? 'border-border bg-muted ml-6 rounded-md border p-3 text-sm'
                : message.status === 'failed'
                  ? 'border-destructive/40 bg-destructive/5 rounded-md border p-3 text-sm'
                  : 'border-border bg-background rounded-md border p-3 text-sm'
            }
          >
            <div className='mb-2 flex items-center justify-between gap-2'>
              <span className='font-medium capitalize'>{message.role}</span>
              <Badge
                variant={
                  message.status === 'failed' ? 'destructive' : 'outline'
                }
                className='capitalize'
              >
                {message.status}
              </Badge>
            </div>
            <p className='whitespace-pre-wrap'>
              {message.content ||
                (message.status === 'streaming' ? 'Working...' : '')}
            </p>
          </article>
        ))}
        {events.slice(-20).map((event) => (
          <article
            key={event._id}
            className='border-border text-muted-foreground rounded-md border border-dashed p-2 text-xs'
          >
            <div className='flex items-center justify-between gap-2'>
              <span className='font-medium capitalize'>
                {event.phase} / {event.level}
              </span>
              <span>{new Date(event.createdAt).toLocaleTimeString()}</span>
            </div>
            <p className='mt-1 whitespace-pre-wrap'>{event.message}</p>
          </article>
        ))}
      </div>
      <div className='border-border space-y-2 border-t p-3'>
        <Textarea
          value={content}
          placeholder='Ask the agent to inspect, explain, or change this fork.'
          disabled={disabled || sending}
          onChange={(event) => setContent(event.target.value)}
        />
        <Button
          type='button'
          className='w-full'
          disabled={disabled || sending || !content.trim()}
          onClick={send}
        >
          <Send className='size-4' />
          {sending ? 'Sending...' : 'Send'}
        </Button>
      </div>
    </div>
  );
};
