const express = require('express');
const { success } = require('../response-helpers');

/**
 * Backups routes factory
 * @param {Object} deps - Explicit dependencies
 * @param {Object} deps.backupManager - Backup management module
 * @param {Function} deps.asyncHandler - Async route handler wrapper
 * @returns {express.Router}
 */
module.exports = function({ backupManager, asyncHandler }) {
  const router = express.Router();

  // Get backup configuration
  router.get('/backups/config', asyncHandler(async (req, res) => {
    const config = backupManager.getConfig();
    success(res, { config });
  }, 'backups-config-get'));

  // Update backup configuration
  router.post('/backups/config', asyncHandler(async (req, res) => {
    backupManager.updateConfig(req.body);
    success(res, { message: 'Backup configuration updated' });
  }, 'backups-config-update'));

  // Execute manual backup
  router.post('/backups/execute', asyncHandler(async (req, res) => {
    const backup = await backupManager.executeBackup('manual', req.body);
    success(res, { backup });
  }, 'backups-execute'));

  // Get backup history
  router.get('/backups/history', asyncHandler(async (req, res) => {
    const limit = parseInt(req.query.limit) || 50;
    const history = backupManager.getHistory(limit);
    success(res, { history });
  }, 'backups-history'));

  // Restore from backup
  router.post('/backups/restore/:backupId', asyncHandler(async (req, res) => {
    const result = await backupManager.restoreBackup(req.params.backupId, req.body);
    success(res, { result });
  }, 'backups-restore'));

  // ==================== CLOUD DESTINATIONS ====================

  // Test a destination (write+read+delete probe)
  router.post('/backups/test-destination', asyncHandler(async (req, res) => {
    const destination = req.body;
    if (!destination || !destination.type) {
      const { ValidationError } = require('../errors');
      throw new ValidationError('destination.type is required');
    }
    const result = await backupManager.testDestination(destination);
    success(res, result);
  }, 'backups-test-destination'));

  // Get cloud credentials (masked) for a provider
  // Provider: dropbox | webdav | sftp
  router.get('/backups/credentials/:provider', asyncHandler(async (req, res) => {
    const credentialManager = require('../credential-manager');
    const provider = req.params.provider;
    if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
      const { ValidationError } = require('../errors');
      throw new ValidationError('Invalid provider');
    }

    const mask = (val) => val ? '***' : null;
    let creds = {};
    if (provider === 'dropbox') {
      const token = await credentialManager.retrieve('backup.dropbox.token');
      creds = { token: mask(token) };
    } else if (provider === 'webdav') {
      creds = {
        url: (await credentialManager.retrieve('backup.webdav.url')) || null,
        username: (await credentialManager.retrieve('backup.webdav.username')) || null,
        password: mask(await credentialManager.retrieve('backup.webdav.password'))
      };
    } else if (provider === 'sftp') {
      creds = {
        host: (await credentialManager.retrieve('backup.sftp.host')) || null,
        port: (await credentialManager.retrieve('backup.sftp.port')) || '22',
        username: (await credentialManager.retrieve('backup.sftp.username')) || null,
        password: mask(await credentialManager.retrieve('backup.sftp.password')),
        privateKey: mask(await credentialManager.retrieve('backup.sftp.privateKey'))
      };
    }
    success(res, { provider, credentials: creds });
  }, 'backups-credentials-get'));

  // Save cloud credentials for a provider
  router.post('/backups/credentials/:provider', asyncHandler(async (req, res) => {
    const credentialManager = require('../credential-manager');
    const { ValidationError } = require('../errors');
    const provider = req.params.provider;

    if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
      throw new ValidationError('Invalid provider');
    }

    const body = req.body || {};
    const storeIfPresent = async (key, val) => {
      if (val !== undefined && val !== null && val !== '' && val !== '***') {
        await credentialManager.store(key, String(val));
      }
    };

    if (provider === 'dropbox') {
      if (!body.token || body.token === '***') {
        const existing = await credentialManager.retrieve('backup.dropbox.token');
        if (!existing) {
          throw new ValidationError('Dropbox token required');
        }
      } else {
        await credentialManager.store('backup.dropbox.token', body.token);
      }
    } else if (provider === 'webdav') {
      await storeIfPresent('backup.webdav.url', body.url);
      await storeIfPresent('backup.webdav.username', body.username);
      await storeIfPresent('backup.webdav.password', body.password);
    } else if (provider === 'sftp') {
      await storeIfPresent('backup.sftp.host', body.host);
      await storeIfPresent('backup.sftp.port', body.port);
      await storeIfPresent('backup.sftp.username', body.username);
      await storeIfPresent('backup.sftp.password', body.password);
      await storeIfPresent('backup.sftp.privateKey', body.privateKey);
    }

    success(res, { message: `${provider} credentials saved` });
  }, 'backups-credentials-set'));

  // Delete cloud credentials for a provider
  router.delete('/backups/credentials/:provider', asyncHandler(async (req, res) => {
    const credentialManager = require('../credential-manager');
    const { ValidationError } = require('../errors');
    const provider = req.params.provider;

    if (!['dropbox', 'webdav', 'sftp'].includes(provider)) {
      throw new ValidationError('Invalid provider');
    }

    const keys = {
      dropbox: ['backup.dropbox.token'],
      webdav: ['backup.webdav.url', 'backup.webdav.username', 'backup.webdav.password'],
      sftp: ['backup.sftp.host', 'backup.sftp.port', 'backup.sftp.username', 'backup.sftp.password', 'backup.sftp.privateKey']
    };

    for (const k of keys[provider]) {
      try { await credentialManager.delete(k); } catch (_) {}
    }

    success(res, { message: `${provider} credentials deleted` });
  }, 'backups-credentials-delete'));

  return router;
};
