/**
 * Platform ops MCP tools — flags.*, jobs.*, maintenance.*, settings.*
 *
 * Backed by: platform-service (port 4003).
 * All tools require admin role.
 */

import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import {
  flagsList,
  flagsGet,
  flagsUpsert,
  flagsDelete,
  flagsKillSwitch,
  jobsList,
  jobsGet,
  jobsTrigger,
  jobsListRuns,
  maintenanceGetCurrent,
  maintenanceSet,
  maintenanceScheduleWindow,
  maintenanceGetSchedule,
  maintenanceDeleteWindow,
  settingsGet,
  settingsUpdate,
  settingsCheckKillSwitch,
} from '../../lib/platform-client.js';
import type { McpToolRequest } from '../tools/types.js';

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

// ── flags.list ────────────────────────────────────────────────────────────────

registerTool({
  name: 'flags.list',
  description:
    'List all feature flags for a product (key, enabled, percentage, platforms, regions). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID to scope the flags'),
  }),
  async execute(args, req) {
    return flagsList({ token: tokenOf(req), requestId: req.id, productId: args.productId });
  },
});

// ── flags.get ─────────────────────────────────────────────────────────────────

registerTool({
  name: 'flags.get',
  description:
    'Get a single feature flag by key including percentage rollout, platform targeting, and region targeting. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    key: z.string().min(1).describe('Flag key (e.g. "new_dashboard", "kill_switch")'),
    productId: z.string().min(1).describe('Product ID'),
  }),
  async execute(args, req) {
    return flagsGet(args.key, {
      token: tokenOf(req),
      requestId: req.id,
      productId: args.productId,
    });
  },
});

// ── flags.upsert ──────────────────────────────────────────────────────────────

registerTool({
  name: 'flags.upsert',
  description:
    'Create or update a feature flag. If the key already exists it is updated; otherwise created. Percentage is 0-100 rollout. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    key: z.string().min(1).describe('Flag key (snake_case, e.g. "new_onboarding_flow")'),
    productId: z.string().min(1).describe('Product ID'),
    enabled: z.boolean().describe('Whether the flag is active'),
    percentage: z.coerce
      .number()
      .min(0)
      .max(100)
      .optional()
      .default(100)
      .describe('Rollout % (0-100)'),
    description: z.string().optional().describe('Human-readable description'),
    platforms: z
      .array(z.string())
      .optional()
      .default([])
      .describe('Platform allowlist (ios, android, web, desktop) — empty = all platforms'),
    regions: z
      .array(z.string())
      .optional()
      .describe('Region allowlist (us, eu, apac) — empty = all regions'),
  }),
  async execute(args, req) {
    const { key, productId, ...input } = args;
    return flagsUpsert(key, input, { token: tokenOf(req), requestId: req.id, productId });
  },
});

// ── flags.delete ──────────────────────────────────────────────────────────────

registerTool({
  name: 'flags.delete',
  description: 'Permanently delete a feature flag by key. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    key: z.string().min(1).describe('Flag key to delete'),
    productId: z.string().min(1).describe('Product ID'),
  }),
  async execute(args, req) {
    return flagsDelete(args.key, {
      token: tokenOf(req),
      requestId: req.id,
      productId: args.productId,
    });
  },
});

// ── flags.killSwitch ──────────────────────────────────────────────────────────

registerTool({
  name: 'flags.killSwitch',
  description:
    'Emergency: disable all flags (or specific keys/platform) at once. Returns list of disabled flag keys and count. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID'),
    platform: z
      .string()
      .optional()
      .describe('Only disable flags for this platform (ios/android/web/desktop)'),
    keys: z
      .array(z.string())
      .optional()
      .describe('Specific flag keys to disable (empty = disable all matching flags)'),
  }),
  async execute(args, req) {
    const { productId, ...input } = args;
    return flagsKillSwitch(input, { token: tokenOf(req), requestId: req.id, productId });
  },
});

// ── jobs.list ─────────────────────────────────────────────────────────────────

registerTool({
  name: 'jobs.list',
  description:
    'List all registered background job definitions (name, schedule, enabled, lastRunAt). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return jobsList({ token: tokenOf(req), requestId: req.id });
  },
});

// ── jobs.get ──────────────────────────────────────────────────────────────────

registerTool({
  name: 'jobs.get',
  description:
    'Get a specific job definition by its ID (e.g. "job_cleanup_expired_sessions"). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    jobId: z.string().min(1).describe('Job definition ID (e.g. "job_cleanup_expired_sessions")'),
  }),
  async execute(args, req) {
    return jobsGet(args.jobId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jobs.trigger ──────────────────────────────────────────────────────────────

registerTool({
  name: 'jobs.trigger',
  description:
    'Manually trigger a named background job outside its normal schedule. Returns the run record with status and timing. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    jobName: z
      .string()
      .min(1)
      .describe('Registered job name (e.g. "cleanup_expired_sessions", "send_daily_brief")'),
  }),
  async execute(args, req) {
    return jobsTrigger(args.jobName, { token: tokenOf(req), requestId: req.id });
  },
});

// ── jobs.listRuns ─────────────────────────────────────────────────────────────

registerTool({
  name: 'jobs.listRuns',
  description:
    'List recent run records for a job (status, startedAt, finishedAt, error if any). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    jobName: z.string().min(1).describe('Job name to get runs for'),
    limit: z.coerce.number().min(1).max(100).default(20),
  }),
  async execute(args, req) {
    return jobsListRuns(args.jobName, args.limit, { token: tokenOf(req), requestId: req.id });
  },
});

// ── maintenance.getCurrent ────────────────────────────────────────────────────

registerTool({
  name: 'maintenance.getCurrent',
  description:
    'Get the current maintenance configuration including mode, bypass rules, message, and upcoming scheduled windows. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return maintenanceGetCurrent({ token: tokenOf(req), requestId: req.id });
  },
});

// ── maintenance.set ───────────────────────────────────────────────────────────

registerTool({
  name: 'maintenance.set',
  description:
    'Set the maintenance mode (none | scheduled | active | emergency). Use "active" for immediate maintenance, "emergency" for critical incidents, "none" to restore service. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    mode: z
      .enum(['none', 'scheduled', 'active', 'emergency'])
      .describe('"none" = service restored, "active" = maintenance now, "emergency" = critical'),
    message: z.string().optional().describe('User-facing maintenance message'),
    affectedServices: z.array(z.string()).optional().describe('List of affected service names'),
    scheduledStart: z
      .string()
      .optional()
      .describe('ISO 8601 scheduled start (for "scheduled" mode)'),
    scheduledEnd: z.string().optional().describe('ISO 8601 scheduled end'),
  }),
  async execute(args, req) {
    return maintenanceSet(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── maintenance.scheduleWindow ────────────────────────────────────────────────

registerTool({
  name: 'maintenance.scheduleWindow',
  description:
    'Schedule a future maintenance window with a title, message, start/end times, and list of affected services. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    title: z.string().min(1).describe('Short title (e.g. "Database migration v2.4")'),
    message: z.string().min(1).describe('User-facing message during the window'),
    mode: z.enum(['scheduled', 'active']).default('scheduled'),
    scheduledStart: z.string().min(1).describe('ISO 8601 start time'),
    scheduledEnd: z.string().min(1).describe('ISO 8601 end time (must be after start)'),
    affectedServices: z.array(z.string()).optional().describe('Affected service names'),
  }),
  async execute(args, req) {
    return maintenanceScheduleWindow(args, { token: tokenOf(req), requestId: req.id });
  },
});

// ── maintenance.getSchedule ──────────────────────────────────────────────────

registerTool({
  name: 'maintenance.getSchedule',
  description:
    'List all upcoming scheduled maintenance windows (title, message, start, end, affectedServices). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({}),
  async execute(_args, req) {
    return maintenanceGetSchedule({ token: tokenOf(req), requestId: req.id });
  },
});

// ── maintenance.deleteWindow ──────────────────────────────────────────────

registerTool({
  name: 'maintenance.deleteWindow',
  description:
    'Cancel (delete) a scheduled maintenance window by its ID. Returns { success: true } on removal. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    windowId: z.string().min(1).describe('Maintenance window ID (mw_… prefix)'),
  }),
  async execute(args, req) {
    return maintenanceDeleteWindow(args.windowId, { token: tokenOf(req), requestId: req.id });
  },
});

// ── settings.get ──────────────────────────────────────────────────────────────

registerTool({
  name: 'settings.get',
  description:
    'Get user settings for the authenticated user (global settings + device overrides map). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID to scope the settings'),
  }),
  async execute(args, req) {
    return settingsGet({ token: tokenOf(req), requestId: req.id, productId: args.productId });
  },
});

// ── settings.update ───────────────────────────────────────────────────────────

registerTool({
  name: 'settings.update',
  description:
    'Merge-update user settings for the authenticated user. Existing keys are preserved; only provided keys are overwritten. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID'),
    settings: z
      .record(z.unknown())
      .describe('Key-value pairs to merge into the user settings object'),
  }),
  async execute(args, req) {
    return settingsUpdate(args.settings, {
      token: tokenOf(req),
      requestId: req.id,
      productId: args.productId,
    });
  },
});

// ── settings.checkKillSwitch ──────────────────────────────────────────────────

registerTool({
  name: 'settings.checkKillSwitch',
  description:
    'Check if the kill_switch feature flag is active for a product (same endpoint that mobile clients poll at launch). Returns { enabled, disabled, message }. No auth required on backend — useful for ops monitoring.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID to check'),
  }),
  async execute(args, req) {
    return settingsCheckKillSwitch(args.productId, { requestId: req.id });
  },
});
