const { readJson, writeJson } = require("./config_manager");

const EMPTY = { users: {}, updated_at: null };

class AiAccessControl {
  constructor(recordAudit = () => {}) {
    this.recordAudit = recordAudit;
  }

  list() {
    const store = readJson("ai_access.json", EMPTY);
    const now = Date.now();
    return Object.entries(store.users || {}).map(([userId, entry]) => ({
      user_id: userId,
      ...entry,
      active: entry.banned || (entry.timeout_until && new Date(entry.timeout_until).getTime() > now)
    })).filter((entry) => entry.active);
  }

  check(userId, context = {}) {
    if (!userId) return deny("anonymous", "AI access requires an identified user.");
    const entry = readJson("ai_access.json", EMPTY).users?.[userId];
    if (!entry) return { allowed: true };
    if (entry.banned) {
      this.audit(userId, "banned", context);
      return deny("banned", entry.reason || "AI access is disabled for this user.", entry.silent);
    }
    if (entry.timeout_until) {
      const until = new Date(entry.timeout_until).getTime();
      if (Number.isFinite(until) && until > Date.now()) {
        this.audit(userId, "timed_out", context);
        return deny("timed_out", entry.reason || "AI access is temporarily unavailable for this user.", entry.silent, entry.timeout_until);
      }
    }
    return { allowed: true };
  }

  set(userId, { action, timeoutUntil = null, reason = "", silent = false, actorId = null }) {
    if (!userId) throw new Error("User id is required.");
    const store = readJson("ai_access.json", EMPTY);
    store.users ||= {};
    if (action === "remove") {
      delete store.users[userId];
    } else if (action === "ban") {
      store.users[userId] = {
        banned: true, timeout_until: null, reason, silent: Boolean(silent),
        updated_at: new Date().toISOString(), updated_by: actorId
      };
    } else if (action === "timeout") {
      const parsed = new Date(timeoutUntil);
      if (Number.isNaN(parsed.getTime()) || parsed.getTime() <= Date.now()) {
        throw new Error("Timeout must be a future timestamp.");
      }
      store.users[userId] = {
        banned: false, timeout_until: parsed.toISOString(), reason, silent: Boolean(silent),
        updated_at: new Date().toISOString(), updated_by: actorId
      };
    } else {
      throw new Error("Unknown access action.");
    }
    store.updated_at = new Date().toISOString();
    writeJson("ai_access.json", store);
    return store.users[userId] || null;
  }

  audit(userId, reason, context) {
    this.recordAudit({
      kind: "access", status: "denied", denial_reason: reason, user_id: userId,
      platform: context.platform || context.origin || "webui",
      channel_id: context.channel_id || null
    });
  }
}

function deny(reason, message, silent = false, until = null) {
  return { allowed: false, reason, message, silent: Boolean(silent), until };
}

module.exports = { AiAccessControl };
