/**
 * Escalation Policy tRPC Router
 * Handles escalation policies, runbooks, and active escalations
 */

import { router, adminProcedure } from '../_core/trpc.ts';
import { escalationPolicyService } from '../services/escalationPolicyService.ts';
import { z } from 'zod';

export const escalationPolicyRouter = router({
  /**
   * List all escalation policies (admin only)
   */
  listPolicies: adminProcedure.query(async () => {
    return escalationPolicyService.listPolicies();
  }),

  /**
   * Get escalation policy by ID (admin only)
   */
  getPolicy: adminProcedure
    .input(z.object({ policyId: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getPolicy(input.policyId);
    }),

  /**
   * Get policies for alert type (admin only)
   */
  getPoliciesForAlertType: adminProcedure
    .input(z.object({ alertType: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getPoliciesForAlertType(input.alertType);
    }),

  /**
   * Create escalation policy (admin only)
   */
  createPolicy: adminProcedure
    .input(
      z.object({
        name: z.string(),
        description: z.string(),
        alertTypes: z.array(z.string()),
        steps: z.array(
          z.object({
            step: z.number(),
            minutesAfterAlert: z.number(),
            channels: z.array(z.enum(['slack', 'pagerduty', 'email'])),
            notifyUsers: z.array(z.string()),
            message: z.string().optional(),
          })
        ),
        enabled: z.boolean(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const policy = escalationPolicyService.createPolicy(input);
        return { success: true, policy };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to create policy',
        };
      }
    }),

  /**
   * Update escalation policy (admin only)
   */
  updatePolicy: adminProcedure
    .input(
      z.object({
        policyId: z.string(),
        updates: z.object({
          name: z.string().optional(),
          description: z.string().optional(),
          enabled: z.boolean().optional(),
        }),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const policy = escalationPolicyService.updatePolicy(input.policyId, input.updates);
        return { success: true, policy };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to update policy',
        };
      }
    }),

  /**
   * Delete escalation policy (admin only)
   */
  deletePolicy: adminProcedure
    .input(z.object({ policyId: z.string() }))
    .mutation(async ({ input }) => {
      try {
        const deleted = escalationPolicyService.deletePolicy(input.policyId);
        return {
          success: deleted,
          message: deleted ? 'Policy deleted' : 'Policy not found',
        };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to delete policy',
        };
      }
    }),

  /**
   * List all runbooks (admin only)
   */
  listRunbooks: adminProcedure.query(async () => {
    return escalationPolicyService.listRunbooks();
  }),

  /**
   * Get runbook by ID (admin only)
   */
  getRunbook: adminProcedure
    .input(z.object({ runbookId: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getRunbook(input.runbookId);
    }),

  /**
   * Get runbook for alert type (admin only)
   */
  getRunbookForAlertType: adminProcedure
    .input(z.object({ alertType: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getRunbookForAlertType(input.alertType);
    }),

  /**
   * Create runbook (admin only)
   */
  createRunbook: adminProcedure
    .input(
      z.object({
        alertType: z.string(),
        title: z.string(),
        description: z.string(),
        steps: z.array(z.string()),
        estimatedResolutionTime: z.number(),
        tags: z.array(z.string()),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const runbook = escalationPolicyService.createRunbook(input);
        return { success: true, runbook };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to create runbook',
        };
      }
    }),

  /**
   * Update runbook (admin only)
   */
  updateRunbook: adminProcedure
    .input(
      z.object({
        runbookId: z.string(),
        updates: z.object({
          title: z.string().optional(),
          description: z.string().optional(),
          enabled: z.boolean().optional(),
        }),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const runbook = escalationPolicyService.updateRunbook(input.runbookId, input.updates);
        return { success: true, runbook };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to update runbook',
        };
      }
    }),

  /**
   * Delete runbook (admin only)
   */
  deleteRunbook: adminProcedure
    .input(z.object({ runbookId: z.string() }))
    .mutation(async ({ input }) => {
      try {
        const deleted = escalationPolicyService.deleteRunbook(input.runbookId);
        return {
          success: deleted,
          message: deleted ? 'Runbook deleted' : 'Runbook not found',
        };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to delete runbook',
        };
      }
    }),

  /**
   * Start escalation for alert (admin only)
   */
  startEscalation: adminProcedure
    .input(
      z.object({
        alertId: z.string(),
        alertType: z.string(),
        policyId: z.string(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const escalation = escalationPolicyService.startEscalation(
          input.alertId,
          input.alertType,
          input.policyId
        );
        return { success: !!escalation, escalation };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to start escalation',
        };
      }
    }),

  /**
   * Get active escalation (admin only)
   */
  getActiveEscalation: adminProcedure
    .input(z.object({ escalationId: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getActiveEscalation(input.escalationId);
    }),

  /**
   * Get escalations for alert (admin only)
   */
  getEscalationsForAlert: adminProcedure
    .input(z.object({ alertId: z.string() }))
    .query(async ({ input }) => {
      return escalationPolicyService.getEscalationsForAlert(input.alertId);
    }),

  /**
   * Acknowledge escalation (admin only)
   */
  acknowledgeEscalation: adminProcedure
    .input(z.object({ escalationId: z.string() }))
    .mutation(async ({ input }) => {
      try {
        const escalation = escalationPolicyService.acknowledgeEscalation(input.escalationId);
        return { success: !!escalation, escalation };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to acknowledge escalation',
        };
      }
    }),

  /**
   * Resolve escalation (admin only)
   */
  resolveEscalation: adminProcedure
    .input(z.object({ escalationId: z.string() }))
    .mutation(async ({ input }) => {
      try {
        const escalation = escalationPolicyService.resolveEscalation(input.escalationId);
        return { success: !!escalation, escalation };
      } catch (error) {
        return {
          success: false,
          message: error instanceof Error ? error.message : 'Failed to resolve escalation',
        };
      }
    }),

  /**
   * Execute next escalation step (admin only)
   */
  executeNextStep: adminProcedure
    .input(z.object({ escalationId: z.string() }))
    .mutation(async ({ input }) => {
      return escalationPolicyService.executeNextStep(input.escalationId);
    }),

  /**
   * List active escalations (admin only)
   */
  listActiveEscalations: adminProcedure.query(async () => {
    return escalationPolicyService.listActiveEscalations();
  }),

  /**
   * Get escalations due for next step (admin only)
   */
  getEscalationsDueForNextStep: adminProcedure.query(async () => {
    return escalationPolicyService.getEscalationsDueForNextStep();
  }),
});
