/**
 * Strategy para abóbadas cilíndricas (NBR 6123:2023, sec. 6.2.3).
 */

import {
  getVaultCpeWindPerpendicularNBR6123,
  getVaultCpeWindParallelNBR6123,
  type VaultCpeWindPerpendicular,
  type VaultCpeWindParallel,
} from '../nbr-tables/table-15-17';
import {
  getVaultTurbulentCpePerpendicular,
  getVaultTurbulentCpeParallel,
} from '../nbr-tables/table-18-20';

export type VaultRegime = 'laminar-rough' | 'turbulent-51' | 'turbulent-52';

export interface VaultInput {
  /** Flecha f (altura da abóbada) */
  f: number;
  /** Vão ℓ */
  l: number;
  /** Comprimento b */
  b: number;
  /** Velocidade Vk */
  vk: number;
  regime: VaultRegime;
  cpi: number;
}

export interface VaultResult {
  q: number;
  cpi: number;
  windPerpendicular: VaultCpeWindPerpendicular;
  windParallel: VaultCpeWindParallel;
  pressures: Record<string, number>;
}

export function calculateVault(input: VaultInput): VaultResult {
  const { f, l, vk, regime, cpi } = input;
  const q = Number((0.613 * vk * vk / 1000).toFixed(4));
  const fl = f / l;

  let perpendicular: VaultCpeWindPerpendicular;
  let parallel: VaultCpeWindParallel;

  if (regime === 'laminar-rough') {
    perpendicular = getVaultCpeWindPerpendicularNBR6123(fl);
    parallel = getVaultCpeWindParallelNBR6123();
  } else {
    const series = regime === 'turbulent-51' ? 51 : 52;
    perpendicular = getVaultTurbulentCpePerpendicular(fl);
    parallel = getVaultTurbulentCpeParallel(series);
  }

  const pressures: Record<string, number> = {};
  const allCpe: Record<string, number> = { ...perpendicular, ...parallel };
  for (const [k, v] of Object.entries(allCpe)) {
    pressures[k] = Number((q * (v - cpi)).toFixed(3));
  }

  return { q, cpi, windPerpendicular: perpendicular, windParallel: parallel, pressures };
}