/**
 * Tabela 13 — Distribuição das pressões externas em edificações
 * cilíndricas de seção circular (NBR 6123:2023, sec. 6.2.1).
 *
 * Válido para Re > 400 000. Re = 70 000 · Vₖ · d
 *
 * Duas relações h/d e dois tipos de superfície:
 *  - Superfície rugosa (ou com saliências)
 *  - Superfície lisa
 *
 * Fonte: NBR 6123:2023, p. 32 (Tabela 13).
 * Última auditoria: 2026-07-07 — valores oficiais do PDF confirmados.
 *
 * ⚠️ CORREÇÕES vs código anterior:
 *  - rough h/d≥2.5, β=10°: era -0.9, agora +0.9 (sobrepressão)
 *  - smooth h/d=10, β=0°: era -1.0, agora +1.0 (sobrepressão)
 *  - Ângulos intermediários (5°, 15°, etc.) interpolados pela norma
 */

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

/** Ângulos oficiais da Tabela 13 (NBR 6123:2023, p. 32) */
const ANGLES = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 140, 160, 180] as const;

type Surface = 'rough' | 'smooth';
type HeightClass = 'h/d=10' | 'h/d≤2.5';

/**
 * Matriz [surface][heightClass][angle] — valores oficiais da Tabela 13.
 * Cada linha tem 15 valores correspondentes aos ÂNGULOS acima.
 */
const CYL_CPE: Record<Surface, Record<HeightClass, readonly number[]>> = {
  rough: {
    //                   0°   10°   20°   30°   40°   50°    60°    70°    80°    90°   100°  120°  140°  160°  180°
    'h/d=10':          [1.0,  0.9,  0.7,  0.4,  0,   -0.5, -0.95, -1.25, -1.2,  -1.0,  -0.8,  -0.5, -0.4, -0.4, -0.4],
    'h/d≤2.5':         [1.0,  0.9,  0.7,  0.4,  0,   -0.4, -0.8,  -1.1,  -1.05, -0.85, -0.65, -0.35, -0.3, -0.3, -0.3],
  },
  smooth: {
    //                   0°   10°   20°   30°    40°   50°   60°    70°    80°    90°   100°  120°  140°  160°  180°
    'h/d=10':          [1.0,  0.9,  0.7,  0.35,  0,   -0.7, -1.2,  -1.4,  -1.45, -1.4,  -1.1,  -0.6, -0.35, -0.35, -0.35],
    'h/d≤2.5':         [1.0,  0.9,  0.7,  0.35,  0,   -0.5, -1.05, -1.25, -1.3,  -1.2,  -0.85, -0.4, -0.25, -0.25, -0.25],
  },
};

export function getCpeCylinder(
  angleDeg: number,
  hOverD: number,
  surface: Surface,
): number {
  const row2_5 = CYL_CPE[surface]['h/d≤2.5'];
  const row10 = CYL_CPE[surface]['h/d=10'];
  
  const cpe2_5 = linearInterp1D(ANGLES, [...row2_5], angleDeg);
  const cpe10 = linearInterp1D(ANGLES, [...row10], angleDeg);

  let cpeFinal: number;
  if (hOverD <= 2.5) {
    cpeFinal = cpe2_5;
  } else if (hOverD >= 10) {
    cpeFinal = cpe10;
  } else {
    cpeFinal = linearInterp1D([2.5, 10], [cpe2_5, cpe10], hOverD);
  }

  return Number(cpeFinal.toFixed(3));
}

/** Vetor completo de Cpe ao longo da circunferência (19 pontos, 10° em 10°) */
export function getCpeCylinderProfile(
  hOverD: number,
  surface: Surface,
  steps = 19,
): { angle: number; cpe: number }[] {
  const out: { angle: number; cpe: number }[] = [];
  for (let i = 0; i < steps; i++) {
    const angle = (i * 180) / (steps - 1);
    out.push({ angle, cpe: getCpeCylinder(angle, hOverD, surface) });
  }
  return out;
}

/** Reynolds para cilindro: Re = 70 000 · Vₖ · d */
export function reynoldsCylinder(vk: number, d: number): number {
  return 70000 * vk * d;
}

/** Verifica se Re está em regime supercrítico (Re > 400 000) */
export function isSupercritical(re: number): boolean {
  return re > 400000;
}
