/**
 * JarvisJr MCP tools — jarvis.agents.*, jarvis.sessions.*, jarvis.memory.*
 *
 * Backed by: jarvisjr-backend (port 4012).
 * All tools require admin role.
 */

import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import { config } from '../../lib/config.js';
import {
  jarvisAgentCreate,
  jarvisAgentsList,
  jarvisAgentDuplicate,
  jarvisSessionsList,
  jarvisSessionsGetStats,
  jarvisMemoryList,
  jarvisMemoryPrune,
  jarvisMemoryGetContext,
  jarvisMarketplaceListPending,
  jarvisMarketplaceCertify,
  jarvisMarketplaceSuspend,
  jarvisMarketplaceFeature,
  jarvisMemoryCreate,
  jarvisTeamsListMembers,
} from '../../lib/jarvis-client.js';
import type { McpToolRequest } from '../tools/types.js';

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

// ── jarvis.agents.create ─────────────────────────────────────────────────

registerTool({
  name: 'jarvis.agents.create',
  description:
    'Create a new coaching agent with a system prompt, role, and coaching framework. Returns the created agent including its ID. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    name: z.string().min(1).describe('Agent display name'),
    role: z.string().min(1).describe('Agent role (e.g. Career Coach, Language Tutor)'),
    systemPrompt: z.string().min(1).describe('System prompt for the agent'),
    coachingFramework: z.string().optional().describe('Coaching methodology (e.g. GROW, CBT)'),
    voiceId: z.string().optional().describe('TTS voice identifier'),
    difficultyLevel: z
      .enum(['beginner', 'intermediate', 'advanced'])
      .optional()
      .default('intermediate'),
    language: z.string().optional().default('en'),
    privacyLevel: z.enum(['standard', 'strict']).optional().default('standard'),
  }),
  async execute(args, req) {
    return jarvisAgentCreate(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.agents.list ────────────────────────────────────────────────────

registerTool({
  name: 'jarvis.agents.list',
  description:
    'List coaching agents for the authenticated user (name, role, coachingFramework, totalSessions). 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 jarvisAgentsList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.agents.duplicate ───────────────────────────────────────────────

registerTool({
  name: 'jarvis.agents.duplicate',
  description:
    'Duplicate an existing agent (creates a copy with " (Copy)" suffix and zero session count). Useful for iterating on agent prompts. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().min(1).describe('Agent ID to duplicate'),
  }),
  async execute(args, req) {
    return jarvisAgentDuplicate(args.agentId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.sessions.list ──────────────────────────────────────────────────

registerTool({
  name: 'jarvis.sessions.list',
  description:
    'List coaching sessions for the authenticated user. Filter by agentId. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().optional().describe('Filter to a specific agent ID'),
    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 jarvisSessionsList(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.sessions.stats ─────────────────────────────────────────────────

registerTool({
  name: 'jarvis.sessions.stats',
  description:
    'Get coaching session statistics: total sessions, total duration, current streak, per-agent breakdown. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return jarvisSessionsGetStats({ token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.memory.list ────────────────────────────────────────────────────

registerTool({
  name: 'jarvis.memory.list',
  description:
    'List persistent memories for a coaching agent. Filter by type (skill_note, preference, goal, context, exercise) or minimum importance score. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().min(1).describe('Agent ID to query memories for'),
    type: z
      .enum(['skill_note', 'preference', 'goal', 'context', 'exercise'])
      .optional()
      .describe('Filter by memory type'),
    minImportance: z.coerce
      .number()
      .min(0)
      .max(1)
      .optional()
      .describe('Minimum importance score (0.0–1.0)'),
    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) {
    const { agentId, ...params } = args;
    return jarvisMemoryList(agentId, params, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.memory.prune ───────────────────────────────────────────────────

registerTool({
  name: 'jarvis.memory.prune',
  description:
    'Prune expired memories for a coaching agent (removes entries where expiresAt < now). Returns count of pruned entries. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().min(1).describe('Agent ID to prune memories for'),
  }),
  async execute(args, req) {
    return jarvisMemoryPrune(args.agentId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.memory.getContext ──────────────────────────────────────────────

registerTool({
  name: 'jarvis.memory.getContext',
  description:
    'Retrieve the top-N memories for a coaching agent to use as session context (sorted by importance). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().min(1).describe('Agent ID'),
    limit: z.coerce
      .number()
      .min(1)
      .max(50)
      .default(20)
      .describe('Number of context memories to return'),
  }),
  async execute(args, req) {
    return jarvisMemoryGetContext(args.agentId, args.limit, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── jarvis.marketplace.listPending ───────────────────────────────────────

registerTool({
  name: 'jarvis.marketplace.listPending',
  description:
    'List marketplace listings awaiting certification (status = pending_review). For admin use in the certification pipeline. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return jarvisMarketplaceListPending({ token: tokenOf(req), requestId: req.id });
  },
});

// ── jarvis.marketplace.certify ───────────────────────────────────────────

registerTool({
  name: 'jarvis.marketplace.certify',
  description:
    'Approve or reject a marketplace listing. Sets isVerified flag and notifies the author. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    listingId: z.string().min(1).describe('Listing ID'),
    decision: z.enum(['approved', 'rejected']).describe('Certification decision'),
    notes: z.string().optional().describe('Optional review notes for the author'),
  }),
  async execute(args, req) {
    const { listingId, ...decision } = args;
    return jarvisMarketplaceCertify(listingId, decision, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── jarvis.marketplace.suspend ───────────────────────────────────────────

registerTool({
  name: 'jarvis.marketplace.suspend',
  description:
    'Suspend a published marketplace listing (e.g. policy violation). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    listingId: z.string().min(1).describe('Listing ID to suspend'),
    reason: z.string().min(1).describe('Suspension reason shown to the author'),
  }),
  async execute(args, req) {
    return jarvisMarketplaceSuspend(args.listingId, args.reason, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── jarvis.marketplace.feature ───────────────────────────────────────────

registerTool({
  name: 'jarvis.marketplace.feature',
  description:
    'Toggle featured status on a marketplace listing (shows on homepage hero carousel). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    listingId: z.string().min(1).describe('Listing ID'),
    featured: z.boolean().describe('true = feature, false = unfeature'),
  }),
  async execute(args, req) {
    return jarvisMarketplaceFeature(args.listingId, args.featured, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

// ── jarvis.memory.create ──────────────────────────────────────────────────

registerTool({
  name: 'jarvis.memory.create',
  description:
    'Create a persistent memory entry for a coaching agent (skill note, preference, goal, context, or exercise). Used to seed agent context from external data. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    agentId: z.string().min(1).describe('Agent to store memory for'),
    sessionId: z.string().min(1).describe('Session ID that produced this memory'),
    type: z
      .enum(['skill_note', 'preference', 'goal', 'context', 'exercise'])
      .describe('Memory type'),
    content: z.string().min(1).max(5000).describe('Memory content (max 5000 chars)'),
    importance: z.coerce
      .number()
      .min(0)
      .max(1)
      .default(0.5)
      .describe('Importance score 0–1 (default 0.5)'),
    tags: z.array(z.string()).default([]).describe('Optional tags for retrieval'),
    expiresAt: z
      .string()
      .datetime()
      .nullable()
      .optional()
      .describe('ISO 8601 expiry (null = never)'),
  }),
  async execute(args, req) {
    return jarvisMemoryCreate(
      args.agentId,
      {
        sessionId: args.sessionId,
        type: args.type,
        content: args.content,
        importance: args.importance,
        tags: args.tags,
        expiresAt: args.expiresAt ?? null,
      },
      { token: tokenOf(req), requestId: req.id }
    );
  },
});

// ── jarvis.teams.listMembers ──────────────────────────────────────────────

registerTool({
  name: 'jarvis.teams.listMembers',
  description:
    'List members of a JarvisJr enterprise team (role, status, joinedAt). Useful for provisioning audits and team management workflows. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    teamId: z.string().min(1).describe('Team ID'),
  }),
  async execute(args, req) {
    return jarvisTeamsListMembers(args.teamId, { token: tokenOf(req), requestId: req.id });
  },
});
