import { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync } from 'fs';
import { dirname } from 'path';
import { PlatformError } from '../../kernel/errors.mjs';

const SCHEMA_VERSION = 1;

function normalizeState(input = {}) {
  const modules = {};
  const source = input && typeof input === 'object' && !Array.isArray(input) ? input.modules : null;
  if (source && typeof source === 'object' && !Array.isArray(source)) {
    for (const [id, record] of Object.entries(source)) {
      if (!/^vendoo\.[a-z][a-z0-9-]*$/.test(id)) continue;
      if (!record || typeof record !== 'object' || Array.isArray(record)) continue;
      modules[id] = {
        enabled: record.enabled !== false,
        source: String(record.source || 'admin'),
        updatedAt: String(record.updatedAt || new Date(0).toISOString()),
      };
    }
  }
  return { schemaVersion: SCHEMA_VERSION, modules };
}

export class ModuleStateStore {
  #path;
  #state;

  constructor(pathname) {
    this.#path = pathname;
    this.#state = this.#read();
  }

  #read() {
    try {
      if (!existsSync(this.#path)) return normalizeState();
      const parsed = JSON.parse(readFileSync(this.#path, 'utf8'));
      if (Number(parsed?.schemaVersion || 0) !== SCHEMA_VERSION) {
        throw new Error(`Nicht unterstützte Modulstatus-Version: ${parsed?.schemaVersion}`);
      }
      return normalizeState(parsed);
    } catch (error) {
      throw new PlatformError('Der persistente Modulstatus konnte nicht gelesen werden.', {
        code: 'MODULE_STATE_READ_FAILED',
        cause: error,
        details: { path: this.#path },
      });
    }
  }

  #persist() {
    mkdirSync(dirname(this.#path), { recursive: true });
    const temporary = `${this.#path}.${process.pid}.tmp`;
    writeFileSync(temporary, `${JSON.stringify(this.#state, null, 2)}\n`, { mode: 0o600 });
    renameSync(temporary, this.#path);
  }

  has(id) { return Boolean(this.#state.modules[id]); }

  isEnabled(id, fallback = true) {
    const record = this.#state.modules[id];
    return record ? record.enabled !== false : Boolean(fallback);
  }

  setEnabled(id, enabled, { source = 'admin' } = {}) {
    if (!/^vendoo\.[a-z][a-z0-9-]*$/.test(String(id || ''))) {
      throw new PlatformError('Ungültige Modul-ID für den Modulstatus.', { code: 'MODULE_ID_INVALID', status: 400, expose: true });
    }
    this.#state.modules[id] = {
      enabled: Boolean(enabled),
      source: String(source || 'admin').slice(0, 80),
      updatedAt: new Date().toISOString(),
    };
    this.#persist();
    return { id, ...this.#state.modules[id] };
  }

  remove(id) {
    if (!this.#state.modules[id]) return false;
    delete this.#state.modules[id];
    this.#persist();
    return true;
  }

  snapshot() {
    return JSON.parse(JSON.stringify(this.#state));
  }
}
