import { create } from "zustand";
import { api } from "../lib/api.ts";

export interface ConversationMember {
  id: string;
  username: string;
  display_name: string;
  avatar: string;
}

export interface Conversation {
  id: string;
  type: "dm" | "group_dm";
  name: string;
  members: ConversationMember[];
  created_at: string;
}

export interface ConversationMessage {
  id: string;
  conversation_id: string;
  author_id: string;
  author_username: string;
  author_display_name: string | null;
  content: string;
  created_at: string;
  edited_at: string | null;
}

interface ConversationState {
  conversations: Conversation[];
  activeConversationId: string | null;
  messagesByConversation: Record<string, ConversationMessage[]>;
  isLoading: boolean;
  isLoadingOlder: boolean;
  hasMoreByConversation: Record<string, boolean>;
  error: string | null;
  fetchConversations: () => Promise<void>;
  createConversation: (userIds: string[]) => Promise<Conversation>;
  setActiveConversation: (id: string | null) => void;
  fetchMessages: (conversationId: string, before?: string) => Promise<void>;
  fetchOlderMessages: (conversationId: string) => Promise<void>;
  sendMessage: (conversationId: string, content: string) => Promise<ConversationMessage>;
  addMessage: (message: ConversationMessage) => void;
}

export const useConversationStore = create<ConversationState>((set, get) => ({
  conversations: [],
  activeConversationId: null,
  messagesByConversation: {},
  isLoading: false,
  isLoadingOlder: false,
  hasMoreByConversation: {},
  error: null,

  fetchConversations: async () => {
    try {
      const conversations = await api.get<Conversation[]>("/conversations");
      set({ conversations: Array.isArray(conversations) ? conversations : [] });
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : "Failed to fetch conversations",
      });
    }
  },

  createConversation: async (userIds) => {
    const conversation = await api.post<Conversation>("/conversations", { user_ids: userIds });
    set((state) => ({
      conversations: [conversation, ...state.conversations],
      activeConversationId: conversation.id,
    }));
    return conversation;
  },

  setActiveConversation: (id) => set({ activeConversationId: id }),

  fetchMessages: async (conversationId, before) => {
    set({ isLoading: true });
    try {
      const params = before ? "?before=" + encodeURIComponent(before) : "";
      const messages = await api.get<ConversationMessage[]>(
        `/conversations/${conversationId}/messages${params}`,
      );
      const list = Array.isArray(messages) ? messages : [];
      set((state) => ({
        messagesByConversation: {
          ...state.messagesByConversation,
          [conversationId]: list,
        },
        hasMoreByConversation: {
          ...state.hasMoreByConversation,
          [conversationId]: list.length >= 50,
        },
        isLoading: false,
      }));
    } catch (error) {
      set({ isLoading: false, error: error instanceof Error ? error.message : "Failed" });
    }
  },

  fetchOlderMessages: async (conversationId) => {
    const state = get();
    if (state.isLoadingOlder || state.hasMoreByConversation[conversationId] === false) return;
    const existing = state.messagesByConversation[conversationId] || [];
    if (existing.length === 0) return;
    const oldestId = existing[0].id;
    set({ isLoadingOlder: true });
    try {
      const older = await api.get<ConversationMessage[]>(
        `/conversations/${conversationId}/messages?before=${encodeURIComponent(oldestId)}`,
      );
      const list = Array.isArray(older) ? older : [];
      set((state) => ({
        messagesByConversation: {
          ...state.messagesByConversation,
          [conversationId]: [...list, ...existing],
        },
        hasMoreByConversation: {
          ...state.hasMoreByConversation,
          [conversationId]: list.length >= 50,
        },
        isLoadingOlder: false,
      }));
    } catch {
      set({ isLoadingOlder: false });
    }
  },

  sendMessage: async (conversationId, content) => {
    const message = await api.post<ConversationMessage>(
      `/conversations/${conversationId}/messages`,
      { content },
    );
    set((state) => ({
      messagesByConversation: {
        ...state.messagesByConversation,
        [conversationId]: [
          ...(state.messagesByConversation[conversationId] || []),
          message,
        ],
      },
    }));
    return message;
  },

  addMessage: (message) => {
    set((state) => ({
      messagesByConversation: {
        ...state.messagesByConversation,
        [message.conversation_id]: [
          ...(state.messagesByConversation[message.conversation_id] || []),
          message,
        ],
      },
    }));
  },
}));
