/**
 * Tabela 27 — Coeficientes de arrasto Ca para barras prismáticas de
 * seção circular e comprimento infinito (NBR 6123:2023, sec. 8.1.2).
 *
 * Dependem do número de Reynolds: Re = 70 000 · Vk · d
 *
 * Fonte: NBR 6123:2023, p. 53 (Tabela 27).
 * Última auditoria: 2026-07-07 — ⚠️ PENDENTE: revisar valores por
 *   regime de escoamento.
 *
 * PDF página 65.
 *
 * Valores oficiais por regime:
 *   Subcrítico    (Re <  4,2×10⁵):    Ca = 1,2
 *   Acima crítico (4,2×10⁵ ≤ Re < 8,4×10⁵): Ca = 0,6
 *   Acima crítico (8,4×10⁵ ≤ Re < 2,3×10⁶): Ca = 0,7
 *   Supercrítico  (Re ≥ 2,3×10⁶):    Ca = 0,8
 */

import { linearInterp1D } from '../log-interp';

export type ReynoldsRegime = 'subcritical' | 'critical-1' | 'critical-2' | 'supercritical';

/** Determina o regime de escoamento para barra circular */
export function reynoldsRegime(re: number): ReynoldsRegime {
  if (re < 4.2e5) return 'subcritical';
  if (re < 8.4e5) return 'critical-1';
  if (re < 2.3e6) return 'critical-2';
  return 'supercritical';
}

/** Ca por regime */
const CA_BY_REGIME: Record<ReynoldsRegime, number> = {
  subcritical: 1.2,
  'critical-1': 0.6,
  'critical-2': 0.7,
  supercritical: 0.6,
};

export function getCircleBarDragCoefficient(re: number): number {
  return CA_BY_REGIME[reynoldsRegime(re)];
}

/** Reynolds para barra circular: Re = 70 000 · Vk · d */
export function reynoldsBar(vk: number, d: number): number {
  return 70000 * vk * d;
}

export interface CircleBarForceInput {
  /** Diâmetro d (m) */
  d: number;
  /** Comprimento ℓ (m) */
  length: number;
  /** Vk (m/s) */
  vk: number;
  /** Pressão dinâmica q (kN/m²) */
  q: number;
}

export interface CircleBarForceResult {
  re: number;
  regime: ReynoldsRegime;
  ca: number;
  kFactor: number;
  forceKN: number;
}

/** Tabela 28 — Fator K para barra circular em regime subcrítico e supercrítico */
const K_SUB_LCS = [2, 5, 10, 20, 40, 50, 100, 1000] as const;
const K_SUB_VALUES = [0.58, 0.62, 0.68, 0.74, 0.82, 0.87, 0.98, 1.0] as const;
const K_SUPER_LCS = [2, 5, 10, 20, 40, 50, 100, 1000] as const;
const K_SUPER_VALUES = [0.80, 0.80, 0.82, 0.90, 0.98, 0.92, 1.0, 1.0] as const;

function kForBarCircle(lc: number, regime: ReynoldsRegime): number {
  const x = Math.max(2, Math.min(1000, lc));
  if (regime === 'subcritical') {
    return Number(linearInterp1D(K_SUB_LCS, K_SUB_VALUES, x).toFixed(3));
  }
  if (regime === 'supercritical') {
    return Number(linearInterp1D(K_SUPER_LCS, K_SUPER_VALUES, x).toFixed(3));
  }
  return 1.0;
}

export function calculateCircleBarForce(input: CircleBarForceInput): CircleBarForceResult {
  const { d, length, vk, q } = input;
  const re = reynoldsBar(vk, d);
  const regime = reynoldsRegime(re);
  const ca = getCircleBarDragCoefficient(re);
  const lc = length / d;
  const kFactor = kForBarCircle(lc, regime);
  const forceKN = Number((ca * q * d * length * kFactor).toFixed(3));
  return { re, regime, ca, kFactor, forceKN };
}