const express = require('express');
const { exists } = require('../../src/utilities/fs-helpers');
const { logError } = require('../../src/utils/logging');
const { ok } = require('../../src/utils/responses');

module.exports = function({
  docker, caddy, servicesStateManager, asyncHandler, log, helpers,
  errorResponse, dns, siteConfig, buildDomain, SERVICES_FILE, safeErrorMessage
}) {
  const router = express.Router();

  // Ctx shim for backward compatibility with existing route code
  const ctx = {
    dns,
    siteConfig,
    buildDomain,
    SERVICES_FILE,
    safeErrorMessage
  };

  // Remove deployed app
  /**
   * Apps removal routes factory
   * @param {Object} deps - Explicit dependencies
   * @param {Object} deps.docker - Docker client wrapper
   * @param {Object} deps.caddy - Caddy client
   * @param {Object} deps.servicesStateManager - Services state manager
   * @param {Function} deps.asyncHandler - Async route handler wrapper
   * @param {Object} deps.log - Logger instance
   * @param {Object} deps.helpers - Apps helpers module
   * @param {Function} deps.errorResponse - Error response helper
   * @param {Object} deps.dns - DNS context
   * @param {Object} deps.siteConfig - Site configuration
   * @param {Function} deps.buildDomain - Build domain helper
   * @param {string} deps.SERVICES_FILE - Services file path
   * @param {Function} deps.safeErrorMessage - Safe error message formatter
   * @returns {express.Router}
   */
  router.delete('/:appId', asyncHandler(async (req, res) => {
    const { appId } = req.params;
    const { containerId, subdomain, ip, deleteContainer } = req.query;
    const shouldDeleteContainer = deleteContainer === 'true';
    const results = { container: null, dns: null, caddy: null, service: null };

    try {
      log.info('deploy', 'Removing app', { appId, containerId, subdomain, deleteContainer: shouldDeleteContainer });

      if (containerId && shouldDeleteContainer) {
        try {
          const container = docker.client.getContainer(containerId);
          try { await container.stop(); log.info('docker', 'Container stopped', { containerId }); }
          catch (stopError) { log.debug('docker', 'Container stop note', { containerId, note: stopError.message }); }
          await container.remove({ force: true });
          results.container = 'removed';
          log.info('docker', 'Container removed', { containerId });
          // Prune dangling images after removal
          try {
            const pruneResult = await docker.client.pruneImages({ filters: { dangling: { true: true } } });
            if (pruneResult.SpaceReclaimed > 0) {
              log.info('docker', 'Pruned dangling images after removal', { spaceReclaimed: Math.round(pruneResult.SpaceReclaimed / 1024 / 1024) + 'MB' });
            }
          } catch (pruneErr) {
            log.debug('docker', 'Image prune after removal failed', { error: pruneErr.message });
          }
        } catch (error) {
          results.container = error.message.includes('no such container') ? 'already removed' : error.message;
        }
      } else if (containerId && !shouldDeleteContainer) {
        results.container = 'kept (user choice)';
      }

      if (shouldDeleteContainer && subdomain && ctx.dns.getToken()) {
        try {
          const domain = ctx.buildDomain(subdomain);
          const resolveResult = await ctx.dns.universalResolveRecord(domain, 'A');
          let recordIp = ip || 'localhost';
          if (resolveResult) {
            recordIp = resolveResult;
          }
          await ctx.dns.universalDeleteRecord(domain, recordIp);
          results.dns = 'deleted';
          log.info('dns', 'DNS record removal', { result: results.dns });
        } catch (error) {
          results.dns = error.message;
        }
      } else if (!shouldDeleteContainer) {
        results.dns = 'kept (user choice)';
      } else {
        results.dns = 'skipped (no subdomain or token)';
      }

      if (shouldDeleteContainer && subdomain) {
        try {
          // Check if this service was deployed in subdirectory mode
          const services = await servicesStateManager.read();
          const serviceList = Array.isArray(services) ? services : [];
          const service = serviceList.find(s => s.id === subdomain);

          if (service?.routingMode === 'subdirectory') {
            // Subdirectory mode: remove handle block from inside main domain block
            const subResult = await helpers.removeSubpathConfig(subdomain);
            results.caddy = subResult?.success ? 'removed' : 'not found';
          } else {
            // Subdomain mode: remove standalone domain block
            const domain = ctx.buildDomain(subdomain);
            const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
            const siteBlockRegex = new RegExp(`\\n?${escapedDomain}\\s*\\{[^{}]*(?:\\{[^{}]*(?:\\{[^{}]*\\}[^{}]*)*\\}[^{}]*)*\\}\\s*`, 'g');
            const caddyResult = await caddy.modify(currentContent => {
              const replaced = currentContent.replace(siteBlockRegex, '\n');
              if (replaced.length === currentContent.length) return null;
              return replaced.replace(/\n{3,}/g, '\n\n');
            });
            results.caddy = caddyResult.success ? 'removed' : (caddyResult.rolledBack ? 'removed (reload failed)' : 'not found');
          }
          log.info('caddy', 'Caddy config removal', { result: results.caddy });
        } catch (error) {
          results.caddy = error.message;
        }
      } else if (!shouldDeleteContainer) {
        results.caddy = 'kept (user choice)';
      }

      try {
        if (await exists(ctx.SERVICES_FILE)) {
          let removed = false;
          await servicesStateManager.update(services => {
            const initialLength = services.length;
            const filtered = services.filter(s => s.id !== subdomain);
            removed = filtered.length !== initialLength;
            return filtered;
          });
          results.service = removed ? 'removed' : 'not found';
        }
        log.info('deploy', 'Service config removal', { result: results.service });
      } catch (error) {
        results.service = error.message;
      }

      ok(res, { message: `App ${appId} removal completed`, results });
    } catch (error) {
      await logError('app-removal', error);
      errorResponse(res, 500, ctx.safeErrorMessage(error), { results });
    }
  }, 'apps-delete'));

  return router;
};
