"use client";

import { useState, useRef, useCallback, useEffect } from "react";
import { useEchoStore } from "@/stores/echo-store";
import { cn } from "@/lib/utils";
import { Mic, MicOff, Send, Square, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";

export function ChatInput() {
  const [input, setInput] = useState("");
  const {
    activeConversationId,
    isGenerating,
    isRecording,
    createConversation,
    setIsGenerating,
    appendStreamingContent,
    setStreamingContent,
    addMessage,
    setIsRecording,
  } = useEchoStore();

  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const audioChunksRef = useRef<Blob[]>([]);
  const recognitionRef = useRef<SpeechRecognition | null>(null);

  // Auto-resize textarea
  useEffect(() => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = "auto";
      textarea.style.height = Math.min(textarea.scrollHeight, 160) + "px";
    }
  }, [input]);

  // Cleanup speech recognition on unmount
  useEffect(() => {
    return () => {
      if (recognitionRef.current) {
        recognitionRef.current.abort();
      }
    };
  }, []);

  const sendMessage = useCallback(
    async (text: string) => {
      if (!text.trim() || isGenerating) return;

      let conversationId = activeConversationId;

      // Create conversation if none active
      if (!conversationId) {
        const conv = await createConversation();
        if (!conv) return;
        conversationId = conv.id;
      }

      // Save user message to DB
      const userMsg = await fetch("/api/messages", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          conversationId,
          role: "user",
          content: text.trim(),
        }),
      }).then((r) => r.json());

      addMessage(userMsg);
      setInput("");
      setIsGenerating(true);
      setStreamingContent("");

      try {
        // Stream the response
        const res = await fetch("/api/chat/stream", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            message: text.trim(),
            conversationId,
          }),
        });

        if (!res.body) throw new Error("No response body");

        const reader = res.body.getReader();
        const decoder = new TextDecoder();
        let fullText = "";
        let buffer = "";

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split("\n");
          buffer = lines.pop() || "";

          for (const line of lines) {
            if (line.startsWith("data: ")) {
              const data = line.slice(6).trim();
              if (data === "[DONE]") continue;

              try {
                const parsed = JSON.parse(data);
                if (parsed.token) {
                  appendStreamingContent(parsed.token);
                }
                if (parsed.done) {
                  fullText = parsed.fullText || fullText;
                }
                if (parsed.error) {
                  fullText = parsed.fullText || "Something went wrong.";
                }
              } catch {
                // skip malformed lines
              }
            }
          }
        }

        // Save assistant message to DB
        const assistantMsg = await fetch("/api/messages", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            conversationId,
            role: "assistant",
            content: fullText || "I couldn't generate a response.",
          }),
        }).then((r) => r.json());

        addMessage(assistantMsg);
      } catch (error) {
        console.error("Failed to send message:", error);
        // Save error as assistant message
        const errorMsg = await fetch("/api/messages", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            conversationId,
            role: "assistant",
            content: "Sorry, something went wrong. Please try again.",
          }),
        }).then((r) => r.json());
        addMessage(errorMsg);
      } finally {
        setStreamingContent("");
        setIsGenerating(false);
      }
    },
    [
      activeConversationId,
      isGenerating,
      createConversation,
      setIsGenerating,
      setStreamingContent,
      appendStreamingContent,
      addMessage,
    ]
  );

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    sendMessage(input);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      sendMessage(input);
    }
  };

  // Voice recording using Web Speech API
  const toggleRecording = useCallback(async () => {
    if (isRecording) {
      // Stop recording
      if (recognitionRef.current) {
        recognitionRef.current.stop();
        recognitionRef.current = null;
      }
      setIsRecording(false);
      return;
    }

    // Check for Speech Recognition API
    const SpeechRecognition =
      window.SpeechRecognition || window.webkitSpeechRecognition;

    if (!SpeechRecognition) {
      alert("Speech recognition is not supported in this browser.");
      return;
    }

    const recognition = new SpeechRecognition();
    recognition.continuous = false;
    recognition.interimResults = true;
    recognition.lang = "en-US";

    let finalTranscript = "";

    recognition.onresult = (event: SpeechRecognitionEvent) => {
      let interim = "";
      for (let i = event.resultIndex; i < event.results.length; i++) {
        const transcript = event.results[i][0].transcript;
        if (event.results[i].isFinal) {
          finalTranscript += transcript;
        } else {
          interim += transcript;
        }
      }
      setInput(finalTranscript || interim || input);
    };

    recognition.onend = () => {
      setIsRecording(false);
      recognitionRef.current = null;
      // If we got a final transcript, send it
      if (finalTranscript.trim()) {
        sendMessage(finalTranscript.trim());
      }
    };

    recognition.onerror = (event) => {
      console.error("Speech recognition error:", event.error);
      setIsRecording(false);
      recognitionRef.current = null;
    };

    recognitionRef.current = recognition;
    recognition.start();
    setIsRecording(true);
  }, [isRecording, input, sendMessage, setIsRecording]);

  // Stop recording button
  const StopButton = () => (
    <Button
      type="button"
      size="icon"
      className="h-10 w-10 rounded-full bg-destructive hover:bg-destructive/90 shrink-0"
      onClick={toggleRecording}
    >
      <Square className="h-4 w-4 fill-current" />
    </Button>
  );

  return (
    <div className="border-t border-border bg-card p-4">
      <form
        onSubmit={handleSubmit}
        className="max-w-3xl mx-auto flex items-end gap-3"
      >
        {isRecording ? (
          <StopButton />
        ) : (
          <Button
            type="button"
            size="icon"
            variant="outline"
            className={cn(
              "h-10 w-10 rounded-full shrink-0 transition-colors",
              isRecording && "bg-destructive text-destructive-foreground hover:bg-destructive/90"
            )}
            onClick={toggleRecording}
            disabled={isGenerating}
          >
            <Mic className="h-4 w-4" />
          </Button>
        )}

        <div className="flex-1 relative">
          <Textarea
            ref={textareaRef}
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder={
              isRecording
                ? "Listening..."
                : "Type a message or use the mic..."
            }
            className="min-h-[44px] max-h-[160px] resize-none rounded-2xl pr-12 py-3 text-sm border-border focus-visible:ring-1"
            disabled={isGenerating}
            rows={1}
          />
        </div>

        <Button
          type="submit"
          size="icon"
          className="h-10 w-10 rounded-full shrink-0"
          disabled={!input.trim() || isGenerating}
        >
          {isGenerating ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Send className="h-4 w-4" />
          )}
        </Button>
      </form>

      {isRecording && (
        <div className="flex items-center justify-center gap-2 mt-2">
          <div className="flex gap-1 items-center">
            <span className="w-2 h-2 rounded-full bg-destructive animate-pulse" />
            <span className="text-xs text-muted-foreground">Listening...</span>
          </div>
        </div>
      )}
    </div>
  );
}
