const express = require('express');
const { validateURL, validateToken } = require('../../src/security/input-validator');
const { ValidationError } = require('../../src/utilities/errors');
const { ok, successMessage } = require('../../src/utils/responses');

/**
 * Arr credentials routes factory
 * @param {Object} deps - Explicit dependencies
 * @param {Object} deps.credentialManager - Credential manager
 * @param {Object} deps.servicesStateManager - Services state manager
 * @param {Function} deps.asyncHandler - Async route handler wrapper
 * @param {Function} deps.errorResponse - Error response helper
 * @param {Object} deps.log - Logger instance
 * @param {Object} deps.helpers - Arr helpers module
 * @returns {express.Router}
 */
module.exports = function({ credentialManager, servicesStateManager, asyncHandler, errorResponse, log, helpers }) {
  const router = express.Router();

  // Store arr service credentials
  router.post('/arr/credentials', asyncHandler(async (req, res) => {
    const { service, apiKey, url, seedboxBaseUrl, qualityProfileId, qualityProfileName } = req.body;

    if (!service || !apiKey) {
      throw new ValidationError('Service name and API key required');
    }

    const validServices = ['radarr', 'sonarr', 'prowlarr', 'lidarr', 'plex'];
    if (!validServices.includes(service)) {
      return errorResponse(res, 400, `Invalid service. Must be one of: ${validServices.join(', ')}`);
    }

    // Validate API key format
    try {
      validateToken(apiKey);
    } catch (e) {
      throw new ValidationError('Invalid API key format');
    }

    // Validate URL if provided
    if (url) {
      try { validateURL(url); } catch (e) {
        throw new ValidationError('Invalid URL format');
      }
    }

    // Determine credential key
    const credKey = service === 'plex' ? 'arr.plex.token' : `arr.${service}.apikey`;

    // Build metadata
    const metadata = {
      service,
      source: url ? 'external' : 'local',
      url: url || null,
      storedAt: new Date().toISOString()
    };

    // Test connection if URL is known
    let connectionTest = null;
    let resolvedUrl = url;

    if (!resolvedUrl) {
      // Try to resolve URL from services.json
      try {
        const services = await servicesStateManager.read();
        const svc = Array.isArray(services) ? services : services.services || [];
        const found = svc.find(s => s.id === service && s.isExternal);
        if (found?.externalUrl) resolvedUrl = found.externalUrl;
      } catch (e) { /* ignore */ }
    }

    if (resolvedUrl) {
      connectionTest = await helpers.testServiceConnection(service, resolvedUrl, apiKey);
      if (connectionTest.success) {
        metadata.lastVerified = new Date().toISOString();
        metadata.version = connectionTest.version;
        metadata.url = resolvedUrl;
      }
    }

    // Store quality profile preference if provided
    if (qualityProfileId) {
      metadata.qualityProfileId = qualityProfileId;
      metadata.qualityProfileName = qualityProfileName || null;
    }

    // Store the credential
    const stored = await credentialManager.store(credKey, apiKey, metadata);
    if (!stored) {
      return errorResponse(res, 500, 'Failed to store credential');
    }

    // Optionally store seedbox base URL
    if (seedboxBaseUrl) {
      try { validateURL(seedboxBaseUrl); } catch (e) {
        throw new ValidationError('Invalid seedbox base URL');
      }
      await credentialManager.store('arr.seedbox.baseurl', seedboxBaseUrl, {
        storedAt: new Date().toISOString()
      });
    }

    log.info('arr', 'Stored API key', { service, verified: connectionTest?.success || false });

    ok(res, { message: `${service} API key stored`, connectionTest, url: resolvedUrl });
  }, 'arr-credentials-store'));

  // List stored arr credentials (keys only, not values)
  router.get('/arr/credentials', asyncHandler(async (req, res) => {
    const services = ['radarr', 'sonarr', 'prowlarr', 'lidarr', 'plex'];
    const credentials = {};

    for (const service of services) {
      const credKey = service === 'plex' ? 'arr.plex.token' : `arr.${service}.apikey`;
      const hasKey = !!(await credentialManager.retrieve(credKey));
      const metadata = await credentialManager.getMetadata(credKey);

      credentials[service] = {
        hasKey,
        url: metadata?.url || null,
        lastVerified: metadata?.lastVerified || null,
        version: metadata?.version || null,
        source: metadata?.source || null
      };
    }

    // Get seedbox base URL
    const seedboxBaseUrl = await credentialManager.retrieve('arr.seedbox.baseurl');

    ok(res, { credentials, seedboxBaseUrl: seedboxBaseUrl || null });
  }, 'arr-credentials-list'));

  // Delete stored arr credentials
  router.delete('/arr/credentials/:service', asyncHandler(async (req, res) => {
    const { service } = req.params;
    const credKey = service === 'plex' ? 'arr.plex.token' : `arr.${service}.apikey`;
    await credentialManager.delete(credKey);
    log.info('arr', 'Deleted credentials', { service });
    successMessage(res, `${service} credentials removed`);
  }, 'arr-credentials-delete'));

  return router;
};
