/**
 * Auto-Restart Policy Routes
 *
 * CRUD endpoints for per-container auto-restart policies.
 * Also provides a dry-run test endpoint.
 *
 * @module routes/auto-restart
 */

const express = require('express');
const { success } = require('../src/utils/responses');
const { ValidationError, NotFoundError } = require('../src/utilities/errors');

/**
 * Auto-restart route factory
 *
 * @param {Object} deps - Explicit dependencies
 * @param {Object}   deps.autoRestartManager - AutoRestartManager instance
 * @param {Function} deps.asyncHandler - Async route handler wrapper
 * @param {Function} deps.logError - Error logging function
 * @returns {express.Router}
 */
module.exports = function ({ autoRestartManager, asyncHandler, logError }) {
  const router = express.Router();

  /**
   * GET /auto-restart/policies
   * List all configured auto-restart policies.
   */
  router.get('/policies', asyncHandler(async (_req, res) => {
    const policies = autoRestartManager.listPolicies();
    success(res, { policies });
  }, 'auto-restart-list'));

  /**
   * GET /auto-restart/policies/:serviceId
   * Get the restart policy for a single service.
   */
  router.get('/policies/:serviceId', asyncHandler(async (req, res) => {
    const { serviceId } = req.params;

    if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
      throw new ValidationError('Invalid service ID format');
    }

    const policy = autoRestartManager.getPolicy(serviceId);
    if (!policy) {
      throw new NotFoundError(`Auto-restart policy for "${serviceId}"`);
    }

    success(res, { policy });
  }, 'auto-restart-get'));

  /**
   * POST /auto-restart/policies/:serviceId
   * Create or update a restart policy.
   *
   * Body: { enabled, maxRetries, retryIntervalMs, windowMinutes }
   */
  router.post('/policies/:serviceId', asyncHandler(async (req, res) => {
    const { serviceId } = req.params;

    if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
      throw new ValidationError('Invalid service ID format');
    }

    const { enabled, maxRetries, retryIntervalMs, windowMinutes } = req.body;

    // Validate inputs
    if (enabled !== undefined && typeof enabled !== 'boolean') {
      throw new ValidationError('enabled must be a boolean');
    }
    if (maxRetries !== undefined) {
      if (!Number.isInteger(maxRetries) || maxRetries < 0 || maxRetries > 100) {
        throw new ValidationError('maxRetries must be an integer between 0 and 100');
      }
    }
    if (retryIntervalMs !== undefined) {
      if (!Number.isInteger(retryIntervalMs) || retryIntervalMs < 0 || retryIntervalMs > 3600000) {
        throw new ValidationError('retryIntervalMs must be an integer between 0 and 3600000');
      }
    }
    if (windowMinutes !== undefined) {
      if (!Number.isInteger(windowMinutes) || windowMinutes < 0 || windowMinutes > 1440) {
        throw new ValidationError('windowMinutes must be an integer between 0 and 1440');
      }
    }

    const policy = await autoRestartManager.setPolicy(serviceId, {
      ...(enabled !== undefined && { enabled }),
      ...(maxRetries !== undefined && { maxRetries }),
      ...(retryIntervalMs !== undefined && { retryIntervalMs }),
      ...(windowMinutes !== undefined && { windowMinutes }),
    });

    success(res, { policy, message: `Policy ${serviceId} saved` });
  }, 'auto-restart-set'));

  /**
   * DELETE /auto-restart/policies/:serviceId
   * Remove a restart policy.
   */
  router.delete('/policies/:serviceId', asyncHandler(async (req, res) => {
    const { serviceId } = req.params;

    if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
      throw new ValidationError('Invalid service ID format');
    }

    const removed = await autoRestartManager.removePolicy(serviceId);
    if (!removed) {
      throw new NotFoundError(`Auto-restart policy for "${serviceId}"`);
    }

    success(res, { message: `Policy for "${serviceId}" removed` });
  }, 'auto-restart-delete'));

  /**
   * POST /auto-restart/policies/:serviceId/test
   * Dry-run: simulate a restart attempt without actually restarting.
   * Returns what *would* happen given the current policy state.
   */
  router.post('/policies/:serviceId/test', asyncHandler(async (req, res) => {
    const { serviceId } = req.params;

    if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
      throw new ValidationError('Invalid service ID format');
    }

    const policy = autoRestartManager.getPolicy(serviceId);
    if (!policy) {
      throw new NotFoundError(`Auto-restart policy for "${serviceId}"`);
    }

    const now = Date.now();
    const inCooldown = policy.cooldownUntil && now < policy.cooldownUntil;
    const wouldRetry = !inCooldown && policy.currentRetries < policy.maxRetries;
    const nextAttempt = policy.currentRetries + 1;

    success(res, {
      dryRun: true,
      serviceId,
      policy: {
        enabled: policy.enabled,
        currentRetries: policy.currentRetries,
        maxRetries: policy.maxRetries,
        cooldownUntil: policy.cooldownUntil,
        inCooldown,
      },
      wouldRestart: policy.enabled && wouldRetry,
      wouldMaxOut: !wouldRetry && !inCooldown,
      nextAttempt: wouldRetry ? nextAttempt : null,
      message: !policy.enabled
        ? 'Policy is disabled — no restart would occur'
        : inCooldown
          ? `In cooldown until ${new Date(policy.cooldownUntil).toISOString()} — would skip`
          : wouldRetry
            ? `Would attempt restart ${nextAttempt}/${policy.maxRetries}`
            : `Max retries (${policy.maxRetries}) already reached — would enter cooldown`,
    });
  }, 'auto-restart-test'));

  return router;
};
