import { PlatformError } from './errors.mjs';

const MODULE_ID = /^vendoo\.[a-z][a-z0-9-]*$/;
const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
const CAPABILITY = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
const TYPES = new Set(['core', 'feature', 'adapter', 'extension-host']);
const STATUSES = new Set(['native', 'legacy-bridge', 'disabled']);

function uniqueStrings(values, label, pattern = CAPABILITY) {
  if (!Array.isArray(values)) throw new PlatformError(`${label} muss ein Array sein.`, { code: 'MODULE_MANIFEST_INVALID' });
  const normalized = values.map(value => String(value || '').trim());
  if (normalized.some(value => !pattern.test(value))) {
    throw new PlatformError(`${label} enthält einen ungültigen Eintrag.`, { code: 'MODULE_MANIFEST_INVALID' });
  }
  if (new Set(normalized).size !== normalized.length) {
    throw new PlatformError(`${label} enthält Duplikate.`, { code: 'MODULE_MANIFEST_INVALID' });
  }
  return normalized;
}

export function validateModuleManifest(manifest) {
  if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
    throw new PlatformError('Modulmanifest fehlt oder ist ungültig.', { code: 'MODULE_MANIFEST_INVALID' });
  }
  const normalized = {
    schemaVersion: Number(manifest.schemaVersion || 1),
    id: String(manifest.id || '').trim(),
    name: String(manifest.name || '').trim(),
    version: String(manifest.version || '').trim(),
    type: String(manifest.type || '').trim(),
    status: String(manifest.status || 'native').trim(),
    description: String(manifest.description || '').trim(),
    requires: Object.freeze(uniqueStrings(manifest.requires || [], 'requires', MODULE_ID)),
    permissions: Object.freeze(uniqueStrings(manifest.permissions || [], 'permissions')),
    provides: Object.freeze(uniqueStrings(manifest.provides || [], 'provides')),
    consumes: Object.freeze(uniqueStrings(manifest.consumes || [], 'consumes')),
    owns: Object.freeze(uniqueStrings(manifest.owns || [], 'owns')),
  };
  if (normalized.schemaVersion !== 1) throw new PlatformError('Nicht unterstützte Manifestversion.', { code: 'MODULE_MANIFEST_VERSION' });
  if (!MODULE_ID.test(normalized.id)) throw new PlatformError(`Ungültige Modul-ID: ${normalized.id}`, { code: 'MODULE_ID_INVALID' });
  if (!normalized.name) throw new PlatformError(`Modulname fehlt: ${normalized.id}`, { code: 'MODULE_NAME_REQUIRED' });
  if (!SEMVER.test(normalized.version)) throw new PlatformError(`Ungültige Modulversion: ${normalized.id}`, { code: 'MODULE_VERSION_INVALID' });
  if (!TYPES.has(normalized.type)) throw new PlatformError(`Ungültiger Modultyp: ${normalized.id}`, { code: 'MODULE_TYPE_INVALID' });
  if (!STATUSES.has(normalized.status)) throw new PlatformError(`Ungültiger Modulstatus: ${normalized.id}`, { code: 'MODULE_STATUS_INVALID' });
  if (normalized.requires.includes(normalized.id)) throw new PlatformError(`Modul darf sich nicht selbst benötigen: ${normalized.id}`, { code: 'MODULE_SELF_DEPENDENCY' });
  return Object.freeze(normalized);
}
