import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import {
  diagnosticsListSessions,
  diagnosticsCreateSession,
  diagnosticsGetSession,
  diagnosticsUpdateSession,
  diagnosticsGetLogs,
  diagnosticsGetTraces,
} from '../../lib/platform-client.js';
import { config } from '../../lib/config.js';
import type { McpToolRequest } from '../tools/types.js';

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

registerTool({
  name: 'platform.diagnostics.sessions.list',
  description:
    'List remote debug sessions. Filter by productId, status, or targetUserId. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().optional().describe('Filter by product ID'),
    status: z
      .enum(['pending', 'active', 'paused', 'completed', 'cancelled'])
      .optional()
      .describe('Filter by session status'),
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).optional(),
    offset: z.coerce.number().min(0).optional(),
  }),
  async execute(args, req) {
    return diagnosticsListSessions(args, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.create',
  description:
    'Create a new remote debug session targeting a user or install ID. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    productId: z.string().min(1).describe('Product ID'),
    targetUserId: z.string().optional().describe('User ID to target'),
    targetAnonymousId: z.string().optional().describe('Anonymous install ID to target'),
    collectionLevel: z
      .enum(['standard', 'debug', 'trace'])
      .optional()
      .describe('Collection verbosity'),
    captureLogs: z.boolean().optional().describe('Capture log entries'),
    captureNetwork: z.boolean().optional().describe('Capture network requests'),
    maxDurationMinutes: z.coerce.number().min(5).max(1440).optional().describe('Session TTL'),
  }),
  async execute(args, req) {
    return diagnosticsCreateSession(args, {
      token: tokenOf(req),
      requestId: req.id,
      productId: args.productId,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.get',
  description: 'Get details of a specific debug session by ID. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Debug session ID'),
  }),
  async execute(args, req) {
    return diagnosticsGetSession(args.sessionId, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.update',
  description:
    'Update status or config of a debug session (e.g., pause or complete). Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Debug session ID'),
    status: z
      .enum(['pending', 'active', 'paused', 'completed', 'cancelled'])
      .optional()
      .describe('New session status'),
    collectionLevel: z.enum(['standard', 'debug', 'trace']).optional(),
    maxDurationMinutes: z.coerce.number().min(5).max(1440).optional(),
  }),
  async execute(args, req) {
    const { sessionId, ...body } = args;
    return diagnosticsUpdateSession(sessionId, body, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.getLogs',
  description: 'Retrieve captured log entries for a debug session. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Debug session ID'),
    level: z
      .enum(['debug', 'info', 'warn', 'error', 'fatal'])
      .optional()
      .describe('Filter by log level'),
    from: z.string().optional().describe('ISO 8601 start time'),
    to: z.string().optional().describe('ISO 8601 end time'),
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).optional(),
  }),
  async execute(args, req) {
    const { sessionId, ...params } = args;
    return diagnosticsGetLogs(sessionId, params, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.getTraces',
  description: 'Retrieve OpenTelemetry trace spans for a debug session. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Debug session ID'),
    limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).optional(),
    continuationToken: z.string().optional().describe('Pagination cursor'),
  }),
  async execute(args, req) {
    const { sessionId, ...params } = args;
    return diagnosticsGetTraces(sessionId, params, {
      token: tokenOf(req),
      requestId: req.id,
    });
  },
});

registerTool({
  name: 'platform.diagnostics.sessions.cancel',
  description:
    'Cancel an active remote debug session immediately. Stops further data collection. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Debug session ID to cancel'),
  }),
  async execute(args, req) {
    return diagnosticsUpdateSession(
      args.sessionId,
      { status: 'cancelled' },
      { token: tokenOf(req), requestId: req.id }
    );
  },
});
