const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const { InstanceRegion, InstanceIsLocalStackEnabled, InstanceLocalStackEndpoint } = require("../utils/instanceMgr");

const CHATTER_BASE_URL = process.env.CHATTER_API_BASE_URL || "https://api.chatterresearch.com";

// Configure SecretsManager client with localstack support
const secretsClientOptions = {
  region: InstanceRegion(),
  credentials: defaultProvider()
};

if (InstanceIsLocalStackEnabled()) {
  secretsClientOptions.endpoint = InstanceLocalStackEndpoint();
}

const secretsClient = new SecretsManagerClient(secretsClientOptions);

/**
 * Chatter API Client for making requests to the Chatter API
 */
class ChatterApiClient {
  constructor({ baseUrl, apiToken }) {
    if (!apiToken) throw new Error("ChatterApiClient requires apiToken");
    this.baseUrl = String(baseUrl || "").replace(/\/+$/, "");
    this.apiToken = apiToken;
  }

  async createLocation(companyId, payload) {
    return this.request(`/api/v1/companies/${companyId}/locations`, {
      method: "POST",
      body: payload
    });
  }

  async postInteraction(companyId, payload) {
    return this.request(`/api/v1/companies/${companyId}/solicitation/interaction`, {
      method: "POST",
      body: payload
    });
  }

  async request(path, { method = "GET", body } = {}) {
    const res = await fetch(this.baseUrl + path, {
      method,
      headers: {
        "Api-Token": this.apiToken,
        Accept: "application/json",
        ...(body ? { "Content-Type": "application/json" } : {})
      },
      body: body ? JSON.stringify(body) : undefined
    });

    const text = await res.text();
    const data = text ? safeJson(text) : null;

    if (!res.ok) {
      const err = new Error(`Chatter API error ${res.status} | ${data?.message}`);
      err.status = res.status;
      err.data = data;
      const retryAfterMs = parseRetryAfterMs(res.headers.get("retry-after"));
      if (retryAfterMs != null) err.retryAfterMs = retryAfterMs;
      throw err;
    }
    return data;
  }
}

/**
 * Safely parse JSON, returning original text if parsing fails
 */
function safeJson(text) {
  try {
    return JSON.parse(text);
  } catch {
    return text;
  }
}

function parseRetryAfterMs(value) {
  if (!value) return null;

  const sec = Number(value);
  if (Number.isFinite(sec) && sec >= 0) return Math.ceil(sec * 1000);

  const dateMs = Date.parse(value);
  if (!Number.isFinite(dateMs)) return null;
  return Math.max(0, dateMs - Date.now());
}

/**
 * Fetches Chatter API token from AWS Secrets Manager
 * SecretId format: CHATTER_COMPANY_KEY_<companyId>
 *
 * @param {string|number} companyId - The company ID
 * @returns {Promise<string>} The API token
 */
async function getChatterApiToken(companyId) {
  const key = String(companyId ?? "").trim();
  if (!key) throw new Error("getChatterApiToken: companyId is required");

  // Optional override for development/testing
  if (process.env.CHATTER_API_TOKEN) return process.env.CHATTER_API_TOKEN;

  const secretId = `CHATTER_COMPANY_KEY_${key}`;
  const command = new GetSecretValueCommand({ SecretId: secretId });
  const { SecretString, SecretBinary } = await secretsClient.send(command);

  const token =
    (SecretString && SecretString.trim()) ||
    (SecretBinary && Buffer.from(SecretBinary, "base64").toString("ascii").trim()) ||
    "";

  if (!token) throw new Error(`Chatter API token secret is empty: ${secretId}`);
  return token;
}

/**
 * Creates a Chatter API client instance
 *
 * @param {string|number} companyId - The company ID
 * @param {string} [baseUrl] - Optional base URL override
 * @returns {Promise<ChatterApiClient>} Configured API client
 */
async function createChatterClient(companyId, baseUrl = CHATTER_BASE_URL) {
  const apiToken = await getChatterApiToken(companyId);
  return new ChatterApiClient({ baseUrl, apiToken });
}

module.exports = {
  ChatterApiClient,
  getChatterApiToken,
  createChatterClient,
  safeJson,
  CHATTER_BASE_URL
};
