import { create } from 'zustand';
import { api } from '../lib/api.ts';
import type { Message } from './message.ts';

export interface Thread {
  id: string;
  server_id: string;
  parent_channel_id: string;
  name: string;
  type: 'thread';
  category: string | null;
  position: number;
  archived_at: string | null;
  auto_archive_duration: number;
  message_count: number;
  last_message_at: string | null;
  created_at: string;
  tag_ids?: string[];
}

export interface ForumTag {
  id: string;
  tag_id: string;
  name: string;
  emoji: string | null;
  color: string | null;
}

export interface CreateThreadData {
  name: string;
  message_id?: string;
  tag_ids?: string[];
}

interface ThreadState {
  threadsByParent: Record<string, Thread[]>;
  tagsByForum: Record<string, ForumTag[]>;
  activeThreadId: string | null;
  messagesByThread: Record<string, Message[]>;
  isLoading: boolean;
  error: string | null;
  fetchThreads: (parentChannelId: string) => Promise<void>;
  createThread: (parentChannelId: string, data: CreateThreadData) => Promise<Thread>;
  archiveThread: (threadId: string) => Promise<void>;
  setActiveThread: (id: string | null) => void;
  fetchThreadMessages: (threadId: string, before?: string) => Promise<void>;
  sendThreadMessage: (threadId: string, content: string) => Promise<Message>;
  addThreadMessage: (message: Message) => void;
  fetchForumTags: (forumChannelId: string) => Promise<void>;
  createForumTag: (forumChannelId: string, data: { name: string; emoji?: string; color?: string }) => Promise<ForumTag>;
  deleteForumTag: (tagId: string) => Promise<void>;
}

export const useThreadStore = create<ThreadState>((set) => ({
  threadsByParent: {},
  tagsByForum: {},
  activeThreadId: null,
  messagesByThread: {},
  isLoading: false,
  error: null,

  fetchThreads: async (parentChannelId) => {
    set({ isLoading: true, error: null });
    try {
      const threads = await api.get<Thread[]>(`/channels/${parentChannelId}/threads`);
      set((state) => ({
        threadsByParent: { ...state.threadsByParent, [parentChannelId]: Array.isArray(threads) ? threads : [] },
        isLoading: false,
      }));
    } catch (error) {
      set({ isLoading: false, error: error instanceof Error ? error.message : 'Failed to fetch threads' });
    }
  },

  createThread: async (parentChannelId, data) => {
    const thread = await api.post<Thread>(`/channels/${parentChannelId}/threads`, data);
    set((state) => {
      const list = state.threadsByParent[parentChannelId] || [];
      return {
        threadsByParent: { ...state.threadsByParent, [parentChannelId]: [...list, thread] },
        activeThreadId: thread.id,
      };
    });
    return thread;
  },

  archiveThread: async (threadId) => {
    await api.patch(`/threads/${threadId}`, { archived: true });
    set((state) => {
      const next: Record<string, Thread[]> = {};
      for (const parentId of Object.keys(state.threadsByParent)) {
        next[parentId] = state.threadsByParent[parentId].map((t) =>
          t.id === threadId ? { ...t, archived_at: new Date().toISOString() } : t,
        );
      }
      return { threadsByParent: next };
    });
  },

  setActiveThread: (id) => set({ activeThreadId: id }),

  fetchThreadMessages: async (threadId, before) => {
    set({ isLoading: true, error: null });
    try {
      const params = before ? `?before=${encodeURIComponent(before)}` : '';
      const raw = await api.get<Message[]>(`/channels/${threadId}/messages${params}`);
      // ponytail: API returns DESC (newest first), reverse to oldest-first
      const msgs = (Array.isArray(raw) ? raw : []).reverse();
      set((state) => ({
        messagesByThread: { ...state.messagesByThread, [threadId]: msgs },
        isLoading: false,
      }));
    } catch (error) {
      set({ isLoading: false, error: error instanceof Error ? error.message : 'Failed to fetch thread messages' });
    }
  },

  sendThreadMessage: async (threadId, content) => {
    const message = await api.post<Message>(`/channels/${threadId}/messages`, { content });
    set((state) => {
      const list = state.messagesByThread[threadId] || [];
      return { messagesByThread: { ...state.messagesByThread, [threadId]: [...list, message] } };
    });
    return message;
  },

  addThreadMessage: (message) =>
    set((state) => {
      const list = state.messagesByThread[message.channel_id] || [];
      if (list.some((m) => m.id === message.id)) return state;
      return { messagesByThread: { ...state.messagesByThread, [message.channel_id]: [...list, message] } };
    }),

  fetchForumTags: async (forumChannelId) => {
    const tags = await api.get<ForumTag[]>(`/channels/${forumChannelId}/forum-tags`);
    set((state) => ({
      tagsByForum: { ...state.tagsByForum, [forumChannelId]: Array.isArray(tags) ? tags : [] },
    }));
  },

  createForumTag: async (forumChannelId, data) => {
    const tag = await api.post<ForumTag>(`/channels/${forumChannelId}/forum-tags`, data);
    set((state) => {
      const list = state.tagsByForum[forumChannelId] || [];
      return { tagsByForum: { ...state.tagsByForum, [forumChannelId]: [...list, tag] } };
    });
    return tag;
  },

  deleteForumTag: async (tagId) => {
    await api.delete(`/forum-tags/${tagId}`);
    set((state) => {
      const next: Record<string, ForumTag[]> = {};
      for (const forumId of Object.keys(state.tagsByForum)) {
        next[forumId] = state.tagsByForum[forumId].filter((t) => t.id !== tagId && t.tag_id !== tagId);
      }
      return { tagsByForum: next };
    });
  },
}));
