import fs from 'fs';
import path from 'path';

export type OfficeSettlementProfile = {
  version: string;
  officeId: number;
  externalId: string;
  name: string;
  fineractTenant: string;
  tenantUser: string;
  adminUser: string;
  operatorUser: string;
  settlement: {
    defaultCurrency: string;
    defaultLineId: string;
    moneyLayers: string[];
    glM0: string;
    glM1: string;
    glM2: string;
    glSettlement: string;
    glTradeFinanceContingent: string;
  };
  rails: MiddlewareConfig['rails'];
  omnlLegalName: string;
  omnlLei: string;
};

export type MiddlewareConfig = {
  version: string;
  omnlLegalName: string;
  defaultOfficeId: number;
  enforceSingleOffice?: boolean;
  settlementOffice?: {
    officeId: number;
    externalId: string;
    name: string;
    profilePath: string;
  };
  defaultCurrency: string;
  rails: {
    swift: { enabled: boolean; listenerUrl: string };
    hybx: { enabled: boolean; sidecarUrl: string };
    chain138: { enabled: boolean; rpcEnv: string; defaultLineId: string };
    multiChain?: {
      enabled: boolean;
      registryPath: string;
      primaryChainId: number;
    };
  };
  moneySupply: {
    glM0: string;
    glM1: string;
    glM2: string;
    glSettlement: string;
  };
  production: {
    requireApiKey: boolean;
    allowHybxProduction: boolean;
    allowChainMintExecute: boolean;
    onlineBankMode?: boolean;
  };
};

let cached: MiddlewareConfig | null = null;
let cachedOffice: OfficeSettlementProfile | null = null;

function repoConfigPath(relative: string): string {
  return path.resolve(__dirname, '../../../', relative.replace(/^\//, ''));
}

export function loadConfig(): MiddlewareConfig {
  if (cached) return cached;
  const configPath =
    process.env.SETTLEMENT_MIDDLEWARE_CONFIG ||
    repoConfigPath('config/settlement-middleware.v1.json');
  cached = JSON.parse(fs.readFileSync(configPath, 'utf8')) as MiddlewareConfig;
  return cached;
}

export function loadOfficeProfile(): OfficeSettlementProfile {
  if (cachedOffice) return cachedOffice;
  const cfg = loadConfig();
  const profileRel =
    cfg.settlementOffice?.profilePath ?? 'config/offices/office-24-settlement.v1.json';
  const profilePath = process.env.OMNL_OFFICE_SETTLEMENT_PROFILE || repoConfigPath(profileRel);
  cachedOffice = JSON.parse(fs.readFileSync(profilePath, 'utf8')) as OfficeSettlementProfile;
  return cachedOffice;
}

/** All settlement runs behind Office 24 (Ali HOSPITALLERS). */
export function settlementOfficeId(requested?: number): number {
  const cfg = loadConfig();
  const profile = loadOfficeProfile();
  const locked = cfg.settlementOffice?.officeId ?? profile.officeId ?? cfg.defaultOfficeId;
  const fromEnv = parseInt(
    process.env.ALI_HOSPITALLERS_OFFICE_ID ||
      process.env.OMNL_SETTLEMENT_OFFICE_ID ||
      String(locked),
    10,
  );
  const officeId = fromEnv || locked;

  if (cfg.enforceSingleOffice && requested !== undefined && requested !== officeId) {
    throw new Error(`Settlement is locked to office ${officeId}; requested ${requested}`);
  }
  if (cfg.enforceSingleOffice && officeId !== locked) {
    throw new Error(`Settlement is locked to office ${locked}; env specifies ${officeId}`);
  }
  return officeId;
}

export function port(): number {
  return parseInt(process.env.SETTLEMENT_MIDDLEWARE_PORT || '3011', 10);
}

export function settlementStoreSubdir(): string {
  return `office-${settlementOfficeId()}`;
}
