import { writable, get } from "svelte/store";
import {
  listConversations as listConversationsApi,
  getConversation as getConversationApi,
  createConversation as createConversationApi,
  deleteConversation as deleteConversationApi,
  updateConversation as updateConversationApi,
  conversationChat as conversationChatApi,
  type ConversationDto,
  type ConversationMessageDto,
} from "$lib/backend/conversations";

// ── Store shapes ────────────────────────────────────────────────

type ConversationsState = {
  items: ConversationDto[];
  busy: boolean;
  error: string;
};

type ActiveConversationState = {
  id: string;
  title: string;
  messages: ConversationMessageDto[];
  busy: boolean;
  error: string;
};

// ── Stores ──────────────────────────────────────────────────────

export const conversationsStore = writable<ConversationsState>({
  items: [],
  busy: false,
  error: "",
});

export const activeConversationStore = writable<ActiveConversationState>({
  id: "",
  title: "",
  messages: [],
  busy: false,
  error: "",
});

// ── Actions ─────────────────────────────────────────────────────

export async function loadConversations(): Promise<void> {
  conversationsStore.update((s) => ({ ...s, busy: true, error: "" }));
  try {
    const items = await listConversationsApi();
    conversationsStore.set({ items, busy: false, error: "" });
  } catch (error) {
    conversationsStore.update((s) => ({
      ...s,
      busy: false,
      error: error instanceof Error ? error.message : String(error),
    }));
  }
}

export async function createNewConversation(
  title: string,
): Promise<string | null> {
  try {
    const conv = await createConversationApi(title);
    conversationsStore.update((s) => ({
      ...s,
      items: [conv, ...s.items],
    }));
    // Auto-open the new conversation
    activeConversationStore.set({
      id: conv.id,
      title: conv.title,
      messages: [],
      busy: false,
      error: "",
    });
    return conv.id;
  } catch (error) {
    conversationsStore.update((s) => ({
      ...s,
      error: error instanceof Error ? error.message : String(error),
    }));
    return null;
  }
}

export async function openConversation(id: string): Promise<void> {
  activeConversationStore.update((s) => ({
    ...s,
    id,
    busy: true,
    error: "",
  }));
  try {
    const detail = await getConversationApi(id);
    activeConversationStore.set({
      id: detail.id,
      title: detail.title,
      messages: detail.messages,
      busy: false,
      error: "",
    });
  } catch (error) {
    activeConversationStore.update((s) => ({
      ...s,
      busy: false,
      error: error instanceof Error ? error.message : String(error),
    }));
  }
}

export async function sendConversationMessage(prompt: string): Promise<void> {
  const state = get(activeConversationStore);
  if (!state.id) {
    // Auto-create a conversation from the first message
    const title = prompt.length > 40 ? prompt.slice(0, 37) + "..." : prompt;
    const convId = await createNewConversation(title);
    if (!convId) return;
  }

  const currentId = get(activeConversationStore).id;
  if (!currentId) return;

  // Optimistically add user message
  const tempUserMsg: ConversationMessageDto = {
    id: `temp-${Date.now()}`,
    role: "user",
    text: prompt,
    createdAt: new Date().toISOString(),
  };

  activeConversationStore.update((s) => ({
    ...s,
    messages: [...s.messages, tempUserMsg],
    busy: true,
    error: "",
  }));

  try {
    const result = await conversationChatApi(currentId, prompt);
    activeConversationStore.update((s) => ({
      ...s,
      busy: false,
      // Replace temp user message + add assistant message
      messages: [
        ...s.messages.filter((m) => m.id !== tempUserMsg.id),
        result.userMessage,
        result.assistantMessage,
      ],
    }));
    // Update conversation list (updated_at changes)
    void loadConversations();
  } catch (error) {
    const errorMsg: ConversationMessageDto = {
      id: `error-${Date.now()}`,
      role: "error",
      text: error instanceof Error ? error.message : String(error),
      createdAt: new Date().toISOString(),
    };
    activeConversationStore.update((s) => ({
      ...s,
      busy: false,
      messages: [...s.messages, errorMsg],
    }));
  }
}

export async function renameConversation(
  id: string,
  title: string,
): Promise<void> {
  try {
    await updateConversationApi(id, title);
    conversationsStore.update((s) => ({
      ...s,
      items: s.items.map((c) => (c.id === id ? { ...c, title } : c)),
    }));
    const active = get(activeConversationStore);
    if (active.id === id) {
      activeConversationStore.update((s) => ({ ...s, title }));
    }
  } catch (error) {
    conversationsStore.update((s) => ({
      ...s,
      error: error instanceof Error ? error.message : String(error),
    }));
  }
}

export async function removeConversation(id: string): Promise<void> {
  try {
    await deleteConversationApi(id);
    conversationsStore.update((s) => ({
      ...s,
      items: s.items.filter((c) => c.id !== id),
    }));
    // If this was the active conversation, clear it
    const active = get(activeConversationStore);
    if (active.id === id) {
      clearActiveConversation();
    }
  } catch (error) {
    conversationsStore.update((s) => ({
      ...s,
      error: error instanceof Error ? error.message : String(error),
    }));
  }
}

export function clearActiveConversation(): void {
  activeConversationStore.set({
    id: "",
    title: "",
    messages: [],
    busy: false,
    error: "",
  });
}
