'use strict';

const path = require('path');
const { saveCredentials, loadCredentials } = require('../utils/credentialStore');

const CONFIG_PATH = process.env.CONFIG_PATH || path.join(__dirname, '..', '..', 'config');
const CACHE_PATH = process.env.ARKHON_ENTITLEMENT_CACHE_PATH || path.join(CONFIG_PATH, 'entitlement-cache.enc');
const OFFLINE_GRACE_EXPIRED = 'entitlement_offline_grace_expired';

function nowMs(now = new Date()) {
  return now instanceof Date ? now.getTime() : new Date(now).getTime();
}

function seconds(value, fallback) {
  const n = Number(value);
  return Number.isFinite(n) && n >= 0 ? n : fallback;
}

function sanitizeEntitlement(entitlement = {}) {
  const clone = JSON.parse(JSON.stringify(entitlement || {}));
  if (clone.license) {
    delete clone.license.licenseKey;
    delete clone.license.license_key;
  }
  delete clone.agentKey;
  delete clone.agent_key;
  delete clone.licenseKey;
  delete clone.license_key;
  return clone;
}

function buildRecord(entitlement, now = new Date()) {
  const safe = sanitizeEntitlement(entitlement);
  const cacheTtl = seconds(safe.cache?.ttlSeconds, 300);
  const offlineGrace = seconds(safe.cache?.offlineGraceSeconds, 86400);
  const checkedAtMs = nowMs(now);
  return {
    version: 1,
    checkedAt: new Date(checkedAtMs).toISOString(),
    cacheUntil: new Date(checkedAtMs + cacheTtl * 1000).toISOString(),
    offlineGraceUntil: new Date(checkedAtMs + offlineGrace * 1000).toISOString(),
    lastAllowedAt: safe.allowed === true ? new Date(checkedAtMs).toISOString() : null,
    entitlement: safe,
  };
}

function saveEntitlement(entitlement, options = {}) {
  const record = buildRecord(entitlement, options.now || new Date());
  saveCredentials(options.cachePath || CACHE_PATH, record);
  return record;
}

function readEntitlement(options = {}) {
  try {
    return loadCredentials(options.cachePath || CACHE_PATH);
  } catch (err) {
    if (err.message && err.message.includes('archivo no encontrado')) return null;
    return null;
  }
}

function resolveCachedEntitlement(options = {}) {
  const record = readEntitlement(options);
  if (!record?.entitlement) {
    return {
      ok: true,
      allowed: false,
      status: 'blocked',
      reason: 'entitlement_cache_missing',
      message: 'No existe cache local de permisos.',
      offline: true,
    };
  }

  const current = nowMs(options.now || new Date());
  const entitlement = record.entitlement;
  if (entitlement.allowed === true && new Date(record.offlineGraceUntil).getTime() >= current) {
    return {
      ...entitlement,
      offline: true,
      cache: {
        ...(entitlement.cache || {}),
        checkedAt: record.checkedAt,
        cacheUntil: record.cacheUntil,
        offlineGraceUntil: record.offlineGraceUntil,
      },
    };
  }

  return {
    ok: true,
    allowed: false,
    status: 'blocked',
    reason: OFFLINE_GRACE_EXPIRED,
    message: 'La validacion offline de licencia expiro. Conecta ARKHON Cloud para renovar permisos.',
    offline: true,
    cache: {
      checkedAt: record.checkedAt,
      cacheUntil: record.cacheUntil,
      offlineGraceUntil: record.offlineGraceUntil,
    },
  };
}

async function refreshEntitlement(fetchCloud, options = {}) {
  try {
    const entitlement = await fetchCloud();
    saveEntitlement(entitlement, options);
    return entitlement;
  } catch (err) {
    const cached = resolveCachedEntitlement(options);
    return {
      ...cached,
      cloudError: err.code || err.message || 'entitlement_refresh_failed',
    };
  }
}

module.exports = {
  CACHE_PATH,
  OFFLINE_GRACE_EXPIRED,
  buildRecord,
  saveEntitlement,
  readEntitlement,
  resolveCachedEntitlement,
  refreshEntitlement,
};
