/**
 * Validator untuk argument command line: restforge-cli test
 */
class TestArgumentValidator {

  /**
   * Daftar argument yang valid
   */
  static get validArguments() {
    return {
      project: {
        aliases: ['project'],
        required: false,
        description: 'Nama project',
        example: '--project=mini-inventory'
      },
      endpoint: {
        aliases: ['endpoint'],
        required: false,
        description: 'Nama endpoint yang akan di-generate test-nya',
        example: '--endpoint=category'
      },
      port: {
        aliases: ['port'],
        required: false,
        default: 3000,
        description: 'Port server untuk test',
        example: '--port=3032'
      },
      init: {
        aliases: ['init'],
        required: false,
        default: false,
        validValues: ['true', 'false'],
        description: 'Buat template test-data.json',
        example: '--init'
      },
      force: {
        aliases: ['force'],
        required: false,
        default: false,
        validValues: ['true', 'false'],
        description: 'Timpa file test yang sudah ada',
        example: '--force=true'
      }
    };
  }

  /**
   * Parse arguments dari command line
   * @param {Array<string>} args - Array argument dari process.argv.slice(2)
   * @returns {Object} Parsed arguments object
   */
  static parseArguments(args) {
    const parsed = {
      project: null,
      endpoint: null,
      port: 3000,
      init: false,
      force: false,
      help: false,
      version: false
    };

    if (!args || args.length === 0) {
      parsed.help = true;
      return parsed;
    }

    for (const arg of args) {
      // Handle help flags
      if (arg === '--help' || arg === '-h') {
        parsed.help = true;
        continue;
      }

      // Handle version flags
      if (arg === '--version' || arg === '-v') {
        parsed.version = true;
        continue;
      }

      // Handle --init tanpa value (flag mode)
      if (arg === '--init') {
        parsed.init = true;
        continue;
      }

      // Parse key=value arguments
      if (arg.includes('=')) {
        const [key, ...valueParts] = arg.split('=');
        const value = valueParts.join('=');
        const cleanKey = key.replace(/^--/, '');

        switch (cleanKey) {
          case 'project':
            parsed.project = this.validateName(value, 'project');
            break;

          case 'endpoint':
            parsed.endpoint = this.validateName(value, 'endpoint');
            break;

          case 'port':
            parsed.port = this.validatePort(value);
            break;

          case 'init':
            parsed.init = this.validateBooleanValue(value, 'init');
            break;

          case 'force':
            parsed.force = this.validateBooleanValue(value, 'force');
            break;

          default:
            console.warn(`Warning: Unknown argument '${cleanKey}' will be ignored`);
            break;
        }
      } else {
        console.warn(`Warning: Invalid argument format '${arg}' - expected --key=value format`);
      }
    }

    return parsed;
  }

  /**
   * Validasi arguments yang sudah diparse
   * @param {Object} args - Parsed arguments object
   * @throws {Error} Jika validasi gagal
   */
  static validateArguments(args) {
    if (args.help) {
      this.showHelp();
      process.exit(0);
    }

    if (args.version) {
      console.log('restforge test v1.0.0');
      process.exit(0);
    }

    // --init tanpa endpoint: hanya buat global test-data.json
    if (args.init && !args.endpoint) {
      return; // valid, tidak perlu project/endpoint
    }

    // --init dengan endpoint: perlu project
    if (args.init && args.endpoint && !args.project) {
      throw new Error('Parameter --project is required when using --init with --endpoint');
    }

    // Non-init: perlu project dan endpoint
    if (!args.init) {
      if (!args.project) {
        throw new Error('Parameter --project is required');
      }
      if (!args.endpoint) {
        throw new Error('Parameter --endpoint is required');
      }
    }

    // Log parsed arguments
    console.log('Test generator arguments:');
    if (args.project) console.log(`   Project: ${args.project}`);
    if (args.endpoint) console.log(`   Endpoint: ${args.endpoint}`);
    console.log(`   Port: ${args.port}`);
    console.log(`   Init: ${args.init}`);
    console.log(`   Force: ${args.force}`);
    console.log('');
  }

  // ─── Validators ─────────────────────────────────────────────────────────

  /**
   * Validasi nama (project/endpoint)
   * @param {string} name
   * @param {string} fieldName - Untuk error message
   * @returns {string}
   */
  static validateName(name, fieldName) {
    if (!name || typeof name !== 'string') {
      throw new Error(`${fieldName} name cannot be empty`);
    }

    const trimmed = name.trim();

    if (trimmed.length === 0) {
      throw new Error(`${fieldName} name cannot be empty`);
    }

    if (trimmed.length > 50) {
      throw new Error(`${fieldName} name cannot exceed 50 characters`);
    }

    const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
    if (!validPattern.test(trimmed)) {
      throw new Error(`${fieldName} name can only contain letters, numbers, dash (-), and underscore (_), and must start with a letter or number`);
    }

    if (trimmed.startsWith('-') || trimmed.startsWith('_') ||
        trimmed.endsWith('-') || trimmed.endsWith('_')) {
      throw new Error(`${fieldName} name cannot start or end with dash (-) or underscore (_)`);
    }

    return trimmed.toLowerCase();
  }

  /**
   * Validasi port number
   * @param {string} value
   * @returns {number}
   */
  static validatePort(value) {
    const port = parseInt(value, 10);
    if (isNaN(port) || port < 1 || port > 65535) {
      throw new Error(`Port '${value}' is invalid. Must be a number between 1 and 65535`);
    }
    return port;
  }

  /**
   * Validasi boolean value
   * @param {string} value
   * @param {string} fieldName
   * @returns {boolean}
   */
  static validateBooleanValue(value, fieldName) {
    if (typeof value === 'boolean') return value;

    if (!value || typeof value !== 'string') {
      throw new Error(`${fieldName} value cannot be empty`);
    }

    const trimmed = value.trim().toLowerCase();
    const validTrue = ['true', '1', 'yes', 'y'];
    const validFalse = ['false', '0', 'no', 'n'];

    if (validTrue.includes(trimmed)) return true;
    if (validFalse.includes(trimmed)) return false;

    throw new Error(`${fieldName} value '${value}' is invalid. Valid options: true, false, 1, 0, yes, no`);
  }

  /**
   * Show help message
   */
  static showHelp() {
    console.log(`
Test Generator Tool - Help

DESCRIPTION:
  Generate integration test files (Jest + Supertest) for RESTForge endpoints.
  Tests run against a live server and real database.

USAGE:
  npx restforge test generate [OPTIONS]

OPTIONS:
  --project=<name>    Project name (REQUIRED for generate, OPTIONAL for --init)

  --endpoint=<name>   Endpoint name (REQUIRED for generate)
  --port=<number>     Server port for test requests (DEFAULT: 3000)

  --init              Create test-data.json template files
  --force=<bool>      Overwrite existing files: true|false (DEFAULT: false)

  --help, -h          Show this help message

WORKFLOW:
  1. Initialize test data templates:
     npx restforge test generate --init
     npx restforge test generate --init --project=my-project --endpoint=category

  2. Edit test data files:
     - test-data.json (global field defaults)
     - tests/data/category.test-data.json (per-endpoint data)

  3. Generate test file:
     npx restforge test generate --project=my-project --endpoint=category --port=3032

  4. Run tests:
     npm install
     npm run test:category

EXAMPLES:
  # Init global test data
  npx restforge test generate --init

  # Init per-endpoint test data
  npx restforge test generate --init --project=mini-inventory --endpoint=category

  # Generate test for category endpoint
  npx restforge test generate --project=mini-inventory --endpoint=category

  # Generate with custom port, force overwrite
  npx restforge test generate --project=mini-inventory --endpoint=category --port=3032 --force=true
`);
  }
}

module.exports = TestArgumentValidator;
