/**
 * DC-104: App Catalog API — curated templates with categories and search
 *
 * Exposes the existing app-templates.js as a browsable catalog.
 * GET /api/v1/catalog          — list all apps (with optional category filter)
 * GET /api/v1/catalog/:appId   — get details for a specific app
 * GET /api/v1/catalog/search   — search apps by name/category/keyword
 */
const express = require('express');
const { ok, errorResponse } = require('../src/utils/responses');

// Category mapping for common apps
const CATEGORY_MAP = {
  plex: 'media', jellyfin: 'media', emby: 'media',
  sonarr: 'media', radarr: 'media', prowlarr: 'media', lidarr: 'media',
  readarr: 'media', qbittorrent: 'media', transmission: 'media',
  sabnzbd: 'media', nzbget: 'media',
  nextcloud: 'productivity', vaultwarden: 'productivity',
  gitea: 'development', portainer: 'development', code: 'development',
  node: 'development',
  redis: 'database', postgres: 'database', mariadb: 'database', mongo: 'database',
  mysql: 'database',
  nginx: 'network', caddy: 'network', adguard: 'network', pihole: 'network',
  technitium: 'network', wireguard: 'network',
  homeassistant: 'smart-home', mosquitto: 'smart-home',
  grafana: 'monitoring', prometheus: 'monitoring', uptimekuma: 'monitoring',
};

function getTemplateCategory(template) {
  const id = (template.id || template.name || '').toLowerCase();
  for (const [key, cat] of Object.entries(CATEGORY_MAP)) {
    if (id.includes(key)) return cat;
  }
  return 'other';
}

module.exports = function({ APP_TEMPLATES, asyncHandler } = {}) {
  const wrap = asyncHandler || ((fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next));
  const router = express.Router();

  // GET /api/v1/catalog — list all apps
  router.get('/catalog', wrap(async (req, res) => {
    const { category, sort } = req.query;
    let apps = APP_TEMPLATES || [];
    // APP_TEMPLATES can be an array or an object map { plex: {...}, ... }
    let appArray = Array.isArray(apps) ? apps : Object.values(apps);

    // Build catalog entries
    let entries = appArray.map(t => ({
      id: t.id || t.name?.toLowerCase().replace(/\s+/g, '-'),
      name: t.name,
      description: t.description || '',
      category: getTemplateCategory(t),
      logo: t.logo || null,
      popular: ['plex', 'jellyfin', 'sonarr', 'radarr', 'nextcloud', 'gitea', 'qbittorrent']
        .includes((t.id || t.name || '').toLowerCase().replace(/\s+/g, '-')),
    }));

    // Filter by category
    if (category && category !== 'all') {
      entries = entries.filter(e => e.category === category);
    }

    // Sort
    if (sort === 'name') {
      entries.sort((a, b) => a.name.localeCompare(b.name));
    } else {
      // Default: popular first, then alphabetical
      entries.sort((a, b) => {
        if (a.popular !== b.popular) return a.popular ? -1 : 1;
        return a.name.localeCompare(b.name);
      });
    }

    // Get categories
    const categories = [...new Set(entries.map(e => e.category))].sort();

    ok(res, {
      total: entries.length,
      categories,
      apps: entries,
    });
  }));

  // GET /api/v1/catalog/search?q=plex
  router.get('/catalog/search', wrap(async (req, res) => {
    const q = (req.query.q || '').toLowerCase().trim();
    if (!q) {
      return errorResponse(res, 400, 'Search query (q) is required');
    }

    const allApps = APP_TEMPLATES || [];
    const appArray = Array.isArray(allApps) ? allApps : Object.values(allApps);
    const apps = appArray.filter(t => {
      const name = (t.name || '').toLowerCase();
      const desc = (t.description || '').toLowerCase();
      const cat = getTemplateCategory(t).toLowerCase();
      return name.includes(q) || desc.includes(q) || cat.includes(q);
    }).map(t => ({
      id: t.id || t.name?.toLowerCase().replace(/\s+/g, '-'),
      name: t.name,
      description: t.description || '',
      category: getTemplateCategory(t),
    }));

    ok(res, { query: q, results: apps.length, apps });
  }));

  // GET /api/v1/catalog/:appId — get specific app details
  router.get('/catalog/:appId', wrap(async (req, res) => {
    const appId = req.params.appId;
    const allApps = APP_TEMPLATES || [];
    const appArray = Array.isArray(allApps) ? allApps : Object.values(allApps);
    const app = appArray.find(t => {
      const tid = (t.id || t.name?.toLowerCase().replace(/\s+/g, '-'));
      return tid === appId;
    });

    if (!app) {
      return errorResponse(res, 404, `App '${appId}' not found in catalog`);
    }

    ok(res, {
      id: app.id || appId,
      name: app.name,
      description: app.description || '',
      category: getTemplateCategory(app),
      image: app.image || '',
      ports: app.ports || [],
      env: app.env || {},
      volumes: app.volumes || [],
      network: app.network || 'bridge',
      restart: app.restart || 'unless-stopped',
    });
  }));

  return router;
};
