const fsp = require('fs').promises;
const { validateConfig } = require('../../src/utilities/config-schema');
const { exists } = require('../../src/utilities/fs-helpers');
const { ValidationError } = require('../../src/utilities/errors');
const { ok, successMessage } = require('../../src/utils/responses');

/**
 * Config settings routes factory
 * @param {Object} deps - Explicit dependencies
 * @param {Object} deps.configStateManager - Config state manager
 * @param {Function} deps.asyncHandler - Async route handler wrapper
 * @param {Object} deps.log - Logger instance
 * @param {string} deps.CONFIG_FILE - Config file path
 * @param {Function} deps.errorResponse - Error response helper
 * @param {Function} deps.loadSiteConfig - Site config reload helper
 * @returns {express.Router}
 */
module.exports = function({ configStateManager: _configStateManager, asyncHandler, log, CONFIG_FILE, errorResponse, loadSiteConfig }) {
  const express = require('express');
  const router = express.Router();
  const ctx = { CONFIG_FILE, errorResponse, loadSiteConfig };

  // ===== DASHCADDY CONFIG ENDPOINTS =====
  // Server-side config storage for setup wizard (shared across all browsers/machines)

  router.get('/config', asyncHandler(async (req, res) => {
    if (!await exists(ctx.CONFIG_FILE)) {
      return res.json({ setupComplete: false });
    }
    const data = await fsp.readFile(ctx.CONFIG_FILE, 'utf8');
    const config = JSON.parse(data);
    res.json(config);
  }, 'config-get'));

  router.post('/config', asyncHandler(async (req, res) => {
    const incoming = req.body;

    if (!incoming || typeof incoming !== 'object') {
      throw new ValidationError('Invalid config object');
    }

    // Merge with existing config so partial saves don't wipe fields
    let existing = {};
    if (await exists(ctx.CONFIG_FILE)) {
      try {
        existing = JSON.parse(await fsp.readFile(ctx.CONFIG_FILE, 'utf8'));
      } catch (_) { /* start fresh if file is corrupt */ }
    }
    const config = { ...existing, ...incoming };

    // Merge nested dns object so partial dns updates don't wipe dns fields
    if (existing.dns && incoming.dns) {
      config.dns = { ...existing.dns, ...incoming.dns };
    }
    // Merge nested dnsServers object
    if (existing.dnsServers && incoming.dnsServers) {
      config.dnsServers = { ...existing.dnsServers, ...incoming.dnsServers };
    }

    // Validate merged config against schema
    const { valid, errors, warnings } = validateConfig(config);
    if (!valid) {
      return ctx.errorResponse(res, 400, 'Config validation failed', { errors });
    }

    // Add timestamp
    config.updatedAt = new Date().toISOString();

    await fsp.writeFile(ctx.CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
    if (typeof ctx.loadSiteConfig === 'function') {
      ctx.loadSiteConfig(); // Refresh in-memory config
    }
    log.info('config', 'Config saved', { path: ctx.CONFIG_FILE });

    ok(res, { message: 'Configuration saved', config, warnings });
  }, 'config-save'));

  router.delete('/config', asyncHandler(async (req, res) => {
    if (await exists(ctx.CONFIG_FILE)) {
      await fsp.unlink(ctx.CONFIG_FILE);
    }
    successMessage(res, 'Configuration reset');
  }, 'config-delete'));

  return router;
};
