/**
 * Strategy — torre reticulada (NBR 6123:2023, sec. 8.5).
 *
 * Torre de seção quadrada ou triangular equilátera, formada por
 * barras prismáticas de faces planas ou de seção circular.
 *
 * - Faces planas: Figura 15 (Ca × φ, vento ⊥ face) + fator Kα para vento oblíquo
 * - Circulares quadrada: Figuras 16 (⊥ face) e 17 (diagonal) por Re × φ
 * - Circulares triangular: Figura 18 (vento qq direção) por Re × φ
 */

import { bilinearInterp } from '../bilinear-interp';

/** Figura 15 — Ca para torre faces planas, quadrada e triangular equilátera */
const PHI_15 = [0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0] as const;
const CA_15_QUAD: Readonly<Record<number, number>> = {
  0.05: 3.6, 0.1: 3.0, 0.2: 2.5, 0.3: 2.2, 0.4: 2.0, 0.5: 1.85, 0.6: 1.75, 0.7: 1.65, 0.8: 1.55, 1.0: 1.4,
};

export type TowerSection = 'square' | 'triangular';
export type TowerBarType = 'flat' | 'circular';

export interface TowerInput {
  section: TowerSection;
  barType: TowerBarType;
  /** Índice de área exposta de uma face φ (solidez) */
  phi: number;
  /** Área delimitada pelo contorno da face A (m²) */
  aFace: number;
  /** Ângulo do vento em relação à face (graus, 0–90) */
  alphaWind: 0 | 45 | 90;
  /** Reynolds (para barras circulares) */
  re?: number;
  /** Pressão dinâmica q (kN/m²) */
  q: number;
}

export interface TowerResult {
  ca: number;
  /** Kα — fator de correção para vento oblíquo */
  kAlpha: number;
  /** Ca efetivo após Kα */
  caEff: number;
  /** Força total na torre (kN) */
  forceKN: number;
  /** Componentes por face (Tabela 30) */
  faceComponents: { faceI: number; faceII: number; faceIII: number; faceIV: number };
}

/** Fator Kα para torre quadrada com vento oblíquo */
function kAlphaQuad(alpha: number): number {
  if (alpha <= 12.5) return 1;
  if (alpha <= 20) return 1 + 0.075 * (alpha - 12.5) * 1.333;
  if (alpha <= 45) return 1.16;
  // Extrapolação linear conservadora
  return 1.16;
}

/** Fator Kα para torre triangular equilátera (sempre 1, vento qq direção) */
function kAlphaTriangular(): number {
  return 1;
}

export function calculateTower(input: TowerInput): TowerResult {
  const { section, barType, phi, aFace, alphaWind, re = 0, q } = input;

  let ca = 0;
  if (barType === 'flat') {
    const grid = {
      xs: PHI_15,
      ys: [1] as readonly number[],
      values: [PHI_15.map((p) => CA_15_QUAD[p])],
    };
    const phiClamped = Math.max(0.05, Math.min(1.0, phi));
    ca = bilinearInterp(grid, phiClamped, 1);
  } else {
    // Circulares — Figuras 16/17/18 (simplificado)
    const baseCa = re < 4.2e5 ? 1.5 : re < 2.3e6 ? 0.7 : 0.6;
    ca = Number((baseCa * (0.5 + phi * 1.5)).toFixed(2));
  }

  const kAlpha = section === 'square' ? kAlphaQuad(alphaWind) : kAlphaTriangular();
  const caEff = Number((ca * kAlpha).toFixed(3));
  // A área efetiva (Ae) é a área de contorno (A) multiplicada pela solidez (phi)
  const forceKN = Number((caEff * q * (aFace * phi)).toFixed(3));

  // Componentes por face
  const faceComponents = section === 'square'
    ? alphaWind === 0
      ? { faceI: 1.0, faceII: 0.20, faceIII: 0.20, faceIV: 0.15 }
      : { faceI: 0.50, faceII: 0.37, faceIII: 0.37, faceIV: 0 }
    : { faceI: 1.0, faceII: 1.0, faceIII: 1.0, faceIV: 0 };

  return { ca, kAlpha, caEff, forceKN, faceComponents };
}