/**
 * MindLyst MCP tools — mindlyst.memory.*, mindlyst.brains.*, mindlyst.briefs.*,
 * mindlyst.streaks.*, mindlyst.reflections.*, mindlyst.extractions.*
 *
 * Backed by: mindlyst-backend (port 4014) + extraction-service (port 4005).
 * All tools require admin role.
 */

import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import { config } from '../../lib/config.js';
import {
  mindlystMemoryList,
  mindlystMemoryGetItem,
  mindlystMemoryRetriage,
  mindlystMemoryPatch,
  mindlystMemoryReassign,
  mindlystBrainsList,
  mindlystBriefCreate,
  mindlystBriefsGetToday,
  mindlystBriefsList,
  mindlystStreaksGet,
  mindlystReflectionsList,
} from '../../lib/mindlyst-client.js';
import { extractionRun } from '../../lib/extraction-client.js';
import type { McpToolRequest } from '../tools/types.js';

const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);

// ── mindlyst.memory.get ───────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.get',
  description:
    'Get a single memory item by ID, including its full TriageResult (urgencyScore, emotionScore, confidenceScore, entities, suggestedActions). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    itemId: z.string().min(1).describe('Memory item ID'),
  }),
  async execute(args, req) {
    return mindlystMemoryGetItem(args.itemId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.memory.list ──────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.list',
  description:
    'List MindLyst memory items for the authenticated user. Filter by brain, status, or use free-text. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    brainId: z.string().optional().describe('Filter to a specific Brain ID (e.g. "work", "home")'),
    filter: z
      .enum(['forgotten', 'completed_today'])
      .optional()
      .describe('forgotten = actedOn=false, completed_today = actedOn=true today'),
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
    offset: z.coerce.number().min(0).default(0),
  }),
  async execute(args, req) {
    return mindlystMemoryList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.memory.retriage ──────────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.retriage',
  description:
    'Re-run extraction on a single memory item to refresh its triage result (urgencyScore, suggestedBrainId, entities). Best-effort: returns current item if extraction-service is unavailable. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    itemId: z.string().min(1).describe('Memory item ID'),
  }),
  async execute(args, req) {
    return mindlystMemoryRetriage(args.itemId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.memory.patch ─────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.patch',
  description:
    'Update a memory item status: mark_done, mark_undone, increment_nudge, or set_reminder. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    itemId: z.string().min(1).describe('Memory item ID'),
    action: z.enum(['mark_done', 'mark_undone', 'increment_nudge', 'set_reminder']),
    reminderAt: z
      .string()
      .datetime()
      .optional()
      .describe('ISO 8601 datetime — required when action is set_reminder'),
  }),
  async execute(args, req) {
    return mindlystMemoryPatch(args.itemId, args.action, args.reminderAt, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── mindlyst.memory.reassign ──────────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.reassign',
  description:
    'Reassign a memory item to a different Brain. Records a userCorrection for training. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    itemId: z.string().min(1).describe('Memory item ID'),
    newBrainId: z.string().min(1).describe('Target Brain ID'),
  }),
  async execute(args, req) {
    return mindlystMemoryReassign(args.itemId, args.newBrainId, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── mindlyst.brains.list ──────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.brains.list',
  description:
    'List all Brains for the authenticated user (role-based life OS categories). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
    offset: z.coerce.number().min(0).default(0),
  }),
  async execute(args, req) {
    return mindlystBrainsList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.briefs.getToday ──────────────────────────────────────────────

registerTool({
  name: 'mindlyst.briefs.getToday',
  description:
    "Get today's Daily Brief for the authenticated user. Returns 404 error if none generated yet. Requires admin role.",
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return mindlystBriefsGetToday({ token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.briefs.list ──────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.briefs.list',
  description: 'List past Daily Briefs for the authenticated user. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
    offset: z.coerce.number().min(0).default(0),
  }),
  async execute(args, req) {
    return mindlystBriefsList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.streaks.get ──────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.streaks.get',
  description:
    'Get the current engagement streak for the authenticated user (currentStreak, longestStreak, lastActiveDate). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return mindlystStreaksGet({ token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.reflections.list ─────────────────────────────────────────────

registerTool({
  name: 'mindlyst.reflections.list',
  description: 'List reflection journal entries for the authenticated user. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
    offset: z.coerce.number().min(0).default(0),
  }),
  async execute(args, req) {
    return mindlystReflectionsList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.briefs.generate ────────────────────────────────────────────────

registerTool({
  name: 'mindlyst.briefs.generate',
  description:
    'Trigger generation of a Daily Brief for the authenticated user for a specific date. Assembles greeting, priorityItems[], and brainSummaries from recent memory activity. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    date: z
      .string()
      .regex(/^\d{4}-\d{2}-\d{2}$/)
      .describe('Target date in YYYY-MM-DD format (defaults to today if omitted)')
      .optional(),
  }),
  async execute(args, req) {
    const date = args.date ?? new Date().toISOString().slice(0, 10);
    return mindlystBriefCreate({ date }, { token: tokenOf(req), requestId: req.id });
  },
});

// ── mindlyst.memory.getTriageResult ──────────────────────────────────────────

registerTool({
  name: 'mindlyst.memory.getTriageResult',
  description:
    'Get just the TriageResult sub-document for a memory item: contentType, urgencyScore (0–1), emotionScore (−1–+1), confidenceScore (0–1), suggestedBrainId, entities[], suggestedActions[]. Lighter than mindlyst.memory.get when only triage scoring is needed. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    itemId: z.string().min(1).describe('Memory item ID'),
  }),
  async execute(args, req) {
    const item = await mindlystMemoryGetItem(args.itemId, {
      token: tokenOf(req),
      requestId: req.id,
    });
    return {
      itemId: item.id,
      brainIds: item.brainIds,
      triageResult: item.triageResult ?? null,
    };
  },
});

// ── mindlyst.extractions.run ──────────────────────────────────────────────

registerTool({
  name: 'mindlyst.extractions.run',
  description: [
    'Run text through the MindLyst extraction pipeline with one of the three task IDs:',
    '  • triage — extract brain signals, entities, actions (used for new memory items)',
    '  • memory-insight — summarise a set of memory items into brain-level insights',
    '  • reflection-enrichment — extract themes and highlights from journal text',
    'Requires admin role.',
  ].join('\n'),
  requiredRole: 'admin',
  inputSchema: z.object({
    text: z.string().min(1).describe('Text to extract from'),
    taskId: z
      .enum(['triage', 'memory-insight', 'reflection-enrichment'])
      .default('triage')
      .describe('MindLyst-specific extraction task ID'),
  }),
  async execute(args, req) {
    return extractionRun({ text: args.text, taskId: args.taskId }, { requestId: req.id });
  },
});
