const fs = require("fs");
const path = require("path");
const { getSirayaDataRoot, ensureDir } = require("./paths");
const { getSecret, setSecret, generateApiKey } = require("./secrets");
const { validatePort } = require("./port-utils");

const SETTINGS_VERSION = 1;
let cached = null;
let cachedApiToken = null;

function getSettingsPath() {
  return path.join(getSirayaDataRoot(), "settings.json");
}

function defaultSettings() {
  return {
    version: SETTINGS_VERSION,
    host: "127.0.0.1",
    port: 5000,
    corsOrigins: [
      "http://127.0.0.1:*",
      "http://localhost:*",
      "https://*.siraya.food",
      "https://pos.siraya.food",
    ],
    authEnabled: false,
    authEnforced: false,
    business: {
      name: process.env.BUSINESS_NAME || "SIRAYA",
      tagline: process.env.BUSINESS_TAGLINE || "",
      branch: "",
      address: process.env.BUSINESS_ADDRESS || "",
      phone: process.env.BUSINESS_PHONE || "",
      whatsapp: "",
      website: process.env.BUSINESS_WEBSITE || "",
      ntn: "",
      strn: "",
      taxInfo: "",
    },
    updates: {
      channel: "stable",
      autoCheck: true,
      autoApply: false,
    },
    queue: {
      maxRetentionDays: 30,
      maxJobs: 5000,
    },
    defaultTemplates: {
      customer_receipt: "standard-receipt",
      kitchen_ticket: "kitchen-ticket",
      packing_slip: "packing-slip",
      delivery_receipt: "delivery-receipt",
      invoice_receipt: "invoice-receipt",
    },
    installedVersion: process.env.SERVICE_VERSION || "3.0.0",
    firstRunCompleted: false,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
  };
}

function loadSettings() {
  if (cached) return cached;
  ensureDir(getSirayaDataRoot());
  const filePath = getSettingsPath();
  if (!fs.existsSync(filePath)) {
    cached = defaultSettings();
    saveSettings(cached);
    return cached;
  }
  try {
    cached = { ...defaultSettings(), ...JSON.parse(fs.readFileSync(filePath, "utf8")) };
  } catch {
    cached = defaultSettings();
  }
  return cached;
}

function saveSettings(partial) {
  const current = loadSettings();
  cached = {
    ...current,
    ...partial,
    business: { ...current.business, ...(partial.business || {}) },
    updates: { ...current.updates, ...(partial.updates || {}) },
    queue: { ...current.queue, ...(partial.queue || {}) },
    defaultTemplates: {
      ...current.defaultTemplates,
      ...(partial.defaultTemplates || {}),
    },
    updatedAt: new Date().toISOString(),
  };
  fs.writeFileSync(getSettingsPath(), JSON.stringify(cached, null, 2), "utf8");
  syncEnvFromSettings(cached);
  return cached;
}

function syncEnvFromSettings(settings) {
  process.env.HOST = settings.host || "127.0.0.1";
  process.env.PORT = String(settings.port || 5000);
  if (Array.isArray(settings.corsOrigins)) {
    process.env.CORS_ORIGINS = settings.corsOrigins.join(",");
  }
  if (settings.business?.name) process.env.BUSINESS_NAME = settings.business.name;
  if (settings.business?.tagline) process.env.BUSINESS_TAGLINE = settings.business.tagline;
  if (settings.business?.phone) process.env.BUSINESS_PHONE = settings.business.phone;
  if (settings.business?.website) process.env.BUSINESS_WEBSITE = settings.business.website;
  if (settings.business?.address) process.env.BUSINESS_ADDRESS = settings.business.address;
}

function ensureApiKey() {
  let key = getSecret("printApiToken");
  if (!key) {
    key = generateApiKey();
    setSecret("printApiToken", key);
  }
  cachedApiToken = key;
  if (loadSettings().authEnforced) {
    process.env.PRINT_API_TOKEN = key;
  }
  return key;
}

function getApiToken() {
  if (cachedApiToken) return cachedApiToken;
  cachedApiToken = getSecret("printApiToken") || "";
  return cachedApiToken;
}

function isAuthRequired() {
  const s = loadSettings();
  return Boolean(s.authEnforced && getApiToken());
}

function getPublicSettings() {
  const s = loadSettings();
  const token = getApiToken();
  return {
    version: s.version,
    host: s.host,
    port: s.port,
    corsOrigins: s.corsOrigins,
    authEnabled: s.authEnabled,
    authEnforced: s.authEnforced,
    hasApiKey: Boolean(token),
    apiKeyPreview: token ? `${token.slice(0, 8)}…` : null,
    serviceUrl: `http://${s.host}:${s.port}`,
    business: s.business,
    updates: s.updates,
    defaultTemplates: s.defaultTemplates,
    firstRunCompleted: s.firstRunCompleted,
    installedVersion: s.installedVersion,
    updatedAt: s.updatedAt,
  };
}

function updateSettings(body) {
  const current = loadSettings();
  const next = { ...current };

  if (body.host != null) next.host = String(body.host).trim() || "127.0.0.1";
  if (body.port != null) next.port = validatePort(body.port);
  if (body.corsOrigins != null) {
    next.corsOrigins = Array.isArray(body.corsOrigins)
      ? body.corsOrigins.map(String)
      : String(body.corsOrigins)
          .split(",")
          .map((s) => s.trim())
          .filter(Boolean);
  }
  if (body.authEnabled != null) next.authEnabled = Boolean(body.authEnabled);
  if (body.authEnforced != null) {
    next.authEnforced = Boolean(body.authEnforced);
    ensureApiKey();
    if (next.authEnforced) {
      process.env.PRINT_API_TOKEN = getApiToken();
    } else {
      delete process.env.PRINT_API_TOKEN;
    }
  }
  if (body.business != null) next.business = { ...current.business, ...body.business };
  if (body.updates != null) next.updates = { ...current.updates, ...body.updates };
  if (body.defaultTemplates != null) {
    next.defaultTemplates = { ...current.defaultTemplates, ...body.defaultTemplates };
  }
  if (body.firstRunCompleted != null) {
    next.firstRunCompleted = Boolean(body.firstRunCompleted);
  }

  return saveSettings(next);
}

function regenerateApiKey() {
  const key = generateApiKey();
  setSecret("printApiToken", key);
  cachedApiToken = key;
  const s = loadSettings();
  if (s.authEnforced) process.env.PRINT_API_TOKEN = key;
  return key;
}

function initSettings() {
  const settings = loadSettings();
  syncEnvFromSettings(settings);
  ensureApiKey();
  if (settings.authEnforced) {
    process.env.PRINT_API_TOKEN = getApiToken();
  }
  return settings;
}

module.exports = {
  loadSettings,
  saveSettings,
  getPublicSettings,
  updateSettings,
  ensureApiKey,
  getApiToken,
  isAuthRequired,
  regenerateApiKey,
  initSettings,
  syncEnvFromSettings,
};
