/**
 * btmsg + bttask RPC handlers.
 * Feature 4: Push events on data changes (bttask.changed, btmsg.newMessage).
 */

import type { BtmsgDb } from "../btmsg-db.ts";
import type { BttaskDb } from "../bttask-db.ts";

type RpcSend = { send: Record<string, (...args: unknown[]) => void> };

export function createBtmsgHandlers(btmsgDb: BtmsgDb, rpcRef?: RpcSend) {
  function pushNewMessage(groupId: string, channelId?: string) {
    try { rpcRef?.send?.["btmsg.newMessage"]?.({ groupId, channelId }); } catch { /* non-critical */ }
  }

  return {
    "btmsg.registerAgent": ({ id, name, role, groupId, tier, model }: Record<string, unknown>) => {
      try { btmsgDb.registerAgent(id as string, name as string, role as string, groupId as string, tier as number, model as string); return { ok: true }; }
      catch (err) { console.error("[btmsg.registerAgent]", err); return { ok: false }; }
    },
    "btmsg.getAgents": ({ groupId }: { groupId: string }) => {
      try { return { agents: btmsgDb.getAgents(groupId) }; }
      catch (err) { console.error("[btmsg.getAgents]", err); return { agents: [] }; }
    },
    "btmsg.sendMessage": ({ fromAgent, toAgent, content }: { fromAgent: string; toAgent: string; content: string }) => {
      try {
        const messageId = btmsgDb.sendMessage(fromAgent, toAgent, content);
        // Feature 4: Push DM notification
        const sender = btmsgDb.getAgents("").find(a => a.id === fromAgent);
        pushNewMessage(sender?.groupId ?? "");
        return { ok: true, messageId };
      }
      catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.sendMessage]", err); return { ok: false, error }; }
    },
    "btmsg.listMessages": ({ agentId, otherId, limit }: { agentId: string; otherId: string; limit?: number }) => {
      try { return { messages: btmsgDb.listMessages(agentId, otherId, limit ?? 50) }; }
      catch (err) { console.error("[btmsg.listMessages]", err); return { messages: [] }; }
    },
    "btmsg.markRead": ({ agentId, messageIds }: { agentId: string; messageIds: string[] }) => {
      try { btmsgDb.markRead(agentId, messageIds); return { ok: true }; }
      catch (err) { console.error("[btmsg.markRead]", err); return { ok: false }; }
    },
    "btmsg.listChannels": ({ groupId }: { groupId: string }) => {
      try { return { channels: btmsgDb.listChannels(groupId) }; }
      catch (err) { console.error("[btmsg.listChannels]", err); return { channels: [] }; }
    },
    "btmsg.createChannel": ({ name, groupId, createdBy }: { name: string; groupId: string; createdBy: string }) => {
      try { const channelId = btmsgDb.createChannel(name, groupId, createdBy); return { ok: true, channelId }; }
      catch (err) { console.error("[btmsg.createChannel]", err); return { ok: false }; }
    },
    "btmsg.getChannelMessages": ({ channelId, limit }: { channelId: string; limit?: number }) => {
      try { return { messages: btmsgDb.getChannelMessages(channelId, limit ?? 100) }; }
      catch (err) { console.error("[btmsg.getChannelMessages]", err); return { messages: [] }; }
    },
    "btmsg.sendChannelMessage": ({ channelId, fromAgent, content }: { channelId: string; fromAgent: string; content: string }) => {
      try {
        const messageId = btmsgDb.sendChannelMessage(channelId, fromAgent, content);
        // Feature 4: Push channel message notification
        const channels = btmsgDb.listChannels("");
        const ch = channels.find(c => c.id === channelId);
        pushNewMessage(ch?.groupId ?? "", channelId);
        return { ok: true, messageId };
      }
      catch (err) { console.error("[btmsg.sendChannelMessage]", err); return { ok: false }; }
    },
    // Feature 7: Join/leave channel membership
    "btmsg.joinChannel": ({ channelId, agentId }: { channelId: string; agentId: string }) => {
      try { btmsgDb.joinChannel(channelId, agentId); return { ok: true }; }
      catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.joinChannel]", err); return { ok: false, error }; }
    },
    "btmsg.leaveChannel": ({ channelId, agentId }: { channelId: string; agentId: string }) => {
      try { btmsgDb.leaveChannel(channelId, agentId); return { ok: true }; }
      catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.leaveChannel]", err); return { ok: false, error }; }
    },
    "btmsg.getChannelMembers": ({ channelId }: { channelId: string }) => {
      try { return { members: btmsgDb.getChannelMembers(channelId) }; }
      catch (err) { console.error("[btmsg.getChannelMembers]", err); return { members: [] }; }
    },
    "btmsg.heartbeat": ({ agentId }: { agentId: string }) => {
      try { btmsgDb.heartbeat(agentId); return { ok: true }; }
      catch (err) { console.error("[btmsg.heartbeat]", err); return { ok: false }; }
    },
    "btmsg.getDeadLetters": ({ limit }: { limit?: number }) => {
      try { return { letters: btmsgDb.getDeadLetters(limit ?? 50) }; }
      catch (err) { console.error("[btmsg.getDeadLetters]", err); return { letters: [] }; }
    },
    "btmsg.logAudit": ({ agentId, eventType, detail }: { agentId: string; eventType: string; detail: string }) => {
      try { btmsgDb.logAudit(agentId, eventType, detail); return { ok: true }; }
      catch (err) { console.error("[btmsg.logAudit]", err); return { ok: false }; }
    },
    "btmsg.getAuditLog": ({ limit }: { limit?: number }) => {
      try { return { entries: btmsgDb.getAuditLog(limit ?? 100) }; }
      catch (err) { console.error("[btmsg.getAuditLog]", err); return { entries: [] }; }
    },
  };
}

export function createBttaskHandlers(bttaskDb: BttaskDb, rpcRef?: RpcSend) {
  function pushChanged(groupId: string) {
    try { rpcRef?.send?.["bttask.changed"]?.({ groupId }); } catch { /* non-critical */ }
  }

  return {
    "bttask.listTasks": ({ groupId }: { groupId: string }) => {
      try { return { tasks: bttaskDb.listTasks(groupId) }; }
      catch (err) { console.error("[bttask.listTasks]", err); return { tasks: [] }; }
    },
    "bttask.createTask": ({ title, description, priority, groupId, createdBy, assignedTo }: Record<string, unknown>) => {
      try {
        const taskId = bttaskDb.createTask(title as string, description as string, priority as string, groupId as string, createdBy as string, assignedTo as string);
        pushChanged(groupId as string);
        return { ok: true, taskId };
      }
      catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[bttask.createTask]", err); return { ok: false, error }; }
    },
    "bttask.updateTaskStatus": ({ taskId, status, expectedVersion }: { taskId: string; status: string; expectedVersion: number }) => {
      try {
        const newVersion = bttaskDb.updateTaskStatus(taskId, status, expectedVersion);
        pushChanged(""); // groupId unknown here, frontend will reload
        return { ok: true, newVersion };
      }
      catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[bttask.updateTaskStatus]", err); return { ok: false, error }; }
    },
    "bttask.deleteTask": ({ taskId }: { taskId: string }) => {
      try { bttaskDb.deleteTask(taskId); pushChanged(""); return { ok: true }; }
      catch (err) { console.error("[bttask.deleteTask]", err); return { ok: false }; }
    },
    "bttask.addComment": ({ taskId, agentId, content }: { taskId: string; agentId: string; content: string }) => {
      try { const commentId = bttaskDb.addComment(taskId, agentId, content); return { ok: true, commentId }; }
      catch (err) { console.error("[bttask.addComment]", err); return { ok: false }; }
    },
    "bttask.listComments": ({ taskId }: { taskId: string }) => {
      try { return { comments: bttaskDb.listComments(taskId) }; }
      catch (err) { console.error("[bttask.listComments]", err); return { comments: [] }; }
    },
    "bttask.reviewQueueCount": ({ groupId }: { groupId: string }) => {
      try { return { count: bttaskDb.reviewQueueCount(groupId) }; }
      catch (err) { console.error("[bttask.reviewQueueCount]", err); return { count: 0 }; }
    },
  };
}
