/**
 * DC-100: Service Discovery — auto-detect running Docker containers
 *        and suggest them as services to add to the dashboard.
 *
 * Scans all running containers, extracts port mappings, image info,
 * and labels to suggest service configurations.
 */
const express = require('express');
const { ok, errorResponse } = require('../src/utils/responses');
const { ErrorCodes } = require('../src/utilities/error-codes');

// Known image patterns → suggested service type and default config
const IMAGE_PATTERNS = {
  'plexinc/pms':     { type: 'plex',     name: 'Plex',     port: 32400, https: false },
  'linuxserver/jellyfin': { type: 'jellyfin', name: 'Jellyfin', port: 8096, https: false },
  'linuxserver/emby': { type: 'emby',    name: 'Emby',     port: 8096, https: false },
  'lscr.io/linuxserver/sonarr': { type: 'sonarr', name: 'Sonarr', port: 8989, https: false },
  'lscr.io/linuxserver/radarr': { type: 'radarr', name: 'Radarr', port: 7878, https: false },
  'lscr.io/linuxserver/prowlarr': { type: 'prowlarr', name: 'Prowlarr', port: 9696, https: false },
  'lscr.io/linuxserver/lidarr': { type: 'lidarr', name: 'Lidarr', port: 8686, https: false },
  'lscr.io/linuxserver/readarr': { type: 'readarr', name: 'Readarr', port: 8787, https: false },
  'lscr.io/linuxserver/qbittorrent': { type: 'qbittorrent', name: 'qBittorrent', port: 8080, https: false },
  'lscr.io/linuxserver/transmission': { type: 'transmission', name: 'Transmission', port: 9091, https: false },
  'haugene/transmission-openvpn': { type: 'transmission', name: 'Transmission+VPN', port: 9091, https: false },
  'gitea/gitea':     { type: 'gitea',    name: 'Gitea',    port: 3000, https: false },
  'nextcloud':       { type: 'nextcloud', name: 'Nextcloud', port: 80, https: false },
  'vaultwarden':     { type: 'vaultwarden', name: 'Vaultwarden', port: 80, https: false },
  'nginx':           { type: 'web',      name: 'Nginx',    port: 80, https: false },
  'caddy':           { type: 'web',      name: 'Caddy',    port: 80, https: false },
  'redis':           { type: 'redis',    name: 'Redis',    port: 6379, https: false },
  'postgres':        { type: 'postgres', name: 'PostgreSQL', port: 5432, https: false },
  'mariadb':         { type: 'mariadb',  name: 'MariaDB',  port: 3306, https: false },
  'mongo':           { type: 'mongodb',  name: 'MongoDB',  port: 27017, https: false },
};

module.exports = function({ docker, servicesStateManager, asyncHandler }) {
  const router = express.Router();

  /**
   * GET /api/v1/discover — scan running containers for auto-detection
   *
   * Returns a list of discovered services with suggested configurations.
   * Services already in the dashboard are marked as `existing: true`.
   */
  router.get('/discover', asyncHandler(async (req, res) => {
    if (!docker || !docker.client) {
      return errorResponse(res, 503, 'Docker daemon not available', {
        code: ErrorCodes.CONTAINER.DOCKER_UNREACHABLE,
      });
    }

    try {
      // Get all running containers
      const containers = await docker.client.listContainers({ all: false });

      // Get existing service IDs to mark duplicates
      let existingIds = new Set();
      if (servicesStateManager) {
        try {
          const services = await servicesStateManager.read();
          const list = Array.isArray(services) ? services : (services.services || []);
          existingIds = new Set(list.map(s => s.id));
        } catch { /* ignore — treat as empty */ }
      }

      const discovered = [];
      const seen = new Set();

      for (const container of containers) {
        const name = (container.Names && container.Names[0] || '').replace(/^\//, '');
        if (!name || seen.has(name)) continue;
        seen.add(name);

        const image = container.Image || '';
        const imageBase = image.split(':')[0].toLowerCase();

        // Match against known patterns
        let matched = null;
        for (const [pattern, config] of Object.entries(IMAGE_PATTERNS)) {
          if (imageBase.includes(pattern)) {
            matched = config;
            break;
          }
        }

        // Extract port mappings
        const ports = (container.Ports || []).map(p => ({
          ip: p.IP || '0.0.0.0',
          privatePort: p.PrivatePort,
          publicPort: p.PublicPort,
          type: p.Type || 'tcp',
        })).filter(p => p.publicPort);

        // Suggested config
        const suggestedPort = matched ? matched.port : (ports[0] && ports[0].publicPort) || null;
        const suggestedId = name.replace(/[^a-z0-9-]/gi, '-').toLowerCase();

        discovered.push({
          containerId: container.Id.substring(0, 12),
          name,
          image,
          status: container.State,
          suggested: {
            id: suggestedId,
            name: matched ? matched.name : name.charAt(0).toUpperCase() + name.slice(1),
            type: matched ? matched.type : 'generic',
            port: suggestedPort,
            protocol: matched ? (matched.https ? 'https' : 'http') : 'http',
          },
          ports,
          labels: container.Labels || {},
          existing: existingIds.has(suggestedId),
        });
      }

      // Sort: unmatched first (more interesting to discover), then by name
      discovered.sort((a, b) => {
        if (a.existing !== b.existing) return a.existing ? 1 : -1;
        return a.name.localeCompare(b.name);
      });

      ok(res, {
        total: discovered.length,
        matched: discovered.filter(d => d.suggested.type !== 'generic').length,
        newServices: discovered.filter(d => !d.existing).length,
        discovered,
      });
    } catch (err) {
      return errorResponse(res, 500, `Discovery failed: ${err.message}`, {
        code: ErrorCodes.GENERAL.INTERNAL,
      });
    }
  }));

  return router;
};
