"use client";

import { useCallback, useState, type KeyboardEvent } from "react";
import { Loader2 } from "lucide-react";
import { useToast } from "@mosaic/ui";
import { Button } from "@/components/ui/button";
import { apiPost } from "@/lib/api/client";

const MAX_ROWS = 4;
const TEXTAREA_MAX_HEIGHT_REM = 6.5;

interface BargeInMutationResponse {
  message?: string;
}

export interface BargeInInputProps {
  sessionId: string;
  onSent?: () => void;
}

function getErrorMessage(error: unknown): string {
  if (error instanceof Error && error.message.trim().length > 0) {
    return error.message;
  }
  return "Failed to send message to the session.";
}

export function BargeInInput({ sessionId, onSent }: BargeInInputProps): React.JSX.Element {
  const { showToast } = useToast();
  const [content, setContent] = useState("");
  const [pauseBeforeSend, setPauseBeforeSend] = useState(false);
  const [isSending, setIsSending] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  const handleSend = useCallback(async (): Promise<void> => {
    const trimmedContent = content.trim();
    if (!trimmedContent || isSending) {
      return;
    }

    const encodedSessionId = encodeURIComponent(sessionId);
    const baseEndpoint = `/api/mission-control/sessions/${encodedSessionId}`;
    let didPause = false;
    let didInject = false;

    setIsSending(true);
    setErrorMessage(null);

    try {
      if (pauseBeforeSend) {
        await apiPost<BargeInMutationResponse>(`${baseEndpoint}/pause`);
        didPause = true;
      }

      await apiPost<BargeInMutationResponse>(`${baseEndpoint}/inject`, { content: trimmedContent });
      didInject = true;
      setContent("");
      onSent?.();
    } catch (error) {
      const message = getErrorMessage(error);
      setErrorMessage(message);
      showToast(message, "error");
    } finally {
      if (didPause) {
        try {
          await apiPost<BargeInMutationResponse>(`${baseEndpoint}/resume`);
        } catch (resumeError) {
          const resumeMessage = getErrorMessage(resumeError);
          const message = didInject
            ? `Message sent, but failed to resume session: ${resumeMessage}`
            : `Failed to resume session: ${resumeMessage}`;
          setErrorMessage(message);
          showToast(message, "error");
        }
      }

      setIsSending(false);
    }
  }, [content, isSending, onSent, pauseBeforeSend, sessionId, showToast]);

  const handleKeyDown = useCallback(
    (event: KeyboardEvent<HTMLTextAreaElement>): void => {
      if (event.key === "Enter" && !event.shiftKey) {
        event.preventDefault();
        void handleSend();
      }
    },
    [handleSend]
  );

  const isSendDisabled = isSending || content.trim().length === 0;

  return (
    <div className="space-y-2">
      <textarea
        value={content}
        onChange={(event) => {
          setContent(event.target.value);
        }}
        onKeyDown={handleKeyDown}
        disabled={isSending}
        rows={MAX_ROWS}
        placeholder="Inject a message into this session..."
        className="block w-full resize-y rounded-md border border-border bg-background px-3 py-2 text-sm leading-5 text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-60"
        style={{ maxHeight: `${String(TEXTAREA_MAX_HEIGHT_REM)}rem` }}
        aria-label="Inject message"
      />
      <div className="flex items-center justify-between gap-3">
        <label className="flex items-center gap-2 text-sm text-muted-foreground">
          <input
            type="checkbox"
            checked={pauseBeforeSend}
            onChange={(event) => {
              setPauseBeforeSend(event.target.checked);
            }}
            disabled={isSending}
            className="h-4 w-4 rounded border-border"
          />
          <span>Pause before send</span>
        </label>
        <Button
          type="button"
          variant="primary"
          size="sm"
          disabled={isSendDisabled}
          onClick={() => {
            void handleSend();
          }}
        >
          {isSending ? (
            <span className="flex items-center gap-2">
              <Loader2 className="h-4 w-4 animate-spin" aria-hidden="true" />
              Sending...
            </span>
          ) : (
            "Send"
          )}
        </Button>
      </div>
      {errorMessage ? (
        <p role="alert" className="text-sm text-red-500">
          {errorMessage}
        </p>
      ) : null}
    </div>
  );
}
