import { useEffect, useRef, useState } from 'react';
import { Link, useParams } from 'react-router-dom';
import { ChevronLeft } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api/client';
import type { Session as SessionType } from '@/api/types';
import { useSessionStream } from '@/hooks/useSessionStream';
import { sessionEvents } from '@/hooks/sessionEvents';
import { MessageList } from '@/components/MessageList';
import { ChatInput } from '@/components/ChatInput';
import { ModelPicker } from '@/components/ModelPicker';

export function Session() {
  const { id } = useParams<{ id: string }>();
  const stream = useSessionStream(id);
  const [session, setSession] = useState<SessionType | null>(null);
  const [name, setName] = useState('');
  const [editingName, setEditingName] = useState(false);
  const lastErrorRef = useRef<string | null>(null);

  useEffect(() => {
    if (stream.error && stream.error !== lastErrorRef.current) {
      lastErrorRef.current = stream.error;
      toast.error(stream.error);
    }
    if (!stream.error) {
      lastErrorRef.current = null;
    }
  }, [stream.error]);

  useEffect(() => {
    if (!id) return;
    setSession(null);
    api.sessions
      .get(id)
      .then((s) => {
        setSession(s);
        setName(s.name);
      })
      .catch(() => {});
  }, [id]);

  useEffect(() => {
    if (!id) return;
    return sessionEvents.subscribe((event) => {
      if (event.type !== 'session_renamed') return;
      if (event.session_id !== id) return;
      setSession((prev) => (prev ? { ...prev, name: event.name } : prev));
      setName((prev) => (editingName ? prev : event.name));
    });
  }, [id, editingName]);

  async function saveName() {
    if (!id || !session) return;
    const trimmed = name.trim();
    if (!trimmed || trimmed === session.name) {
      setName(session.name);
      setEditingName(false);
      return;
    }
    const updated = await api.sessions.update(id, { name: trimmed });
    setSession(updated);
    sessionEvents.emit({
      type: 'session_renamed',
      session_id: id,
      name: trimmed,
    });
    setEditingName(false);
  }

  async function handleSend(content: string) {
    if (!id) return;
    await api.messages.send(id, content);
  }

  const streaming = stream.messages.some((m) => m.status === 'streaming');

  return (
    <div className="flex-1 flex flex-col min-h-0">
      <header className="border-b px-4 py-2 flex items-center gap-2 shrink-0">
        {session && (
          <Link
            to={`/project/${session.project_id}`}
            className="text-muted-foreground hover:text-foreground"
            aria-label="Back to project"
          >
            <ChevronLeft className="size-4" />
          </Link>
        )}
        {editingName ? (
          <input
            autoFocus
            value={name}
            onChange={(e) => setName(e.target.value)}
            onBlur={() => void saveName()}
            onKeyDown={(e) => {
              if (e.key === 'Enter') void saveName();
              if (e.key === 'Escape') {
                setName(session?.name ?? '');
                setEditingName(false);
              }
            }}
            className="bg-transparent border-b border-border px-1 py-0.5 text-sm font-medium outline-none focus:border-ring"
          />
        ) : (
          <button
            type="button"
            className="text-sm font-medium hover:underline"
            onClick={() => setEditingName(true)}
          >
            {session?.name ?? '…'}
          </button>
        )}
        <div className="ml-auto">
          {session && (
            <ModelPicker
              value={session.model}
              onChange={async (model) => {
                const updated = await api.sessions.update(session.id, { model });
                setSession(updated);
              }}
            />
          )}
        </div>
        {!stream.connected && (
          <span className="text-xs text-muted-foreground">reconnecting…</span>
        )}
      </header>

      {id && <MessageList messages={stream.messages} sessionId={id} />}

      <ChatInput disabled={streaming} onSend={handleSend} />
    </div>
  );
}
