import { getEtaTable28 } from '../nbr-tables/table-28';
import { linearInterp1D } from '../log-interp';

export interface PipeDef {
  id: string;
  diameter: number; // diâmetro ou altura do equipamento em metros
}

export interface PiperackInput {
  width: number;       // b: largura do pórtico ortogonal ao vento (m)
  height: number;      // h: altura do pórtico/seção transversal (m)
  elevation: number;   // z: elevação média em relação ao solo (m)
  spacing: number;     // e: distância entre pórticos subsequentes (m)
  numFrames: number;   // n: número de pórticos paralelos na direção do vento
  phiStruct: number;   // φ_str: índice de solidez apenas da estrutura metálica
  pipes: PipeDef[];    // Lista de tubulações correndo longitudinalmente
  q: number;           // q: Pressão dinâmica na elevação z (kN/m²)
}

export interface PiperackResult {
  phiTotal: number;
  caFrontal: number;
  eta: number;
  linearLoadFront: number; // kN/m (carga no pórtico 1)
  linearLoadBack: number;  // kN/m (carga nos pórticos 2..n)
  globalForce: number;     // kN (força total na estrutura)
}

/** Tabela de Ca genérica para reticulados planos (faces planas) baseada na solidez φ */
const PHI_ARRAY = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6];
const CA_FLAT_ARRAY = [2.8, 2.4, 2.0, 1.8, 1.7, 1.6];

export function calculatePiperack(input: PiperackInput): PiperackResult {
  const { width, height, spacing, numFrames, phiStruct, pipes, q } = input;

  // 1. Calcular o Índice de Solidez Total (φ)
  const phiPipes = pipes.reduce((sum, pipe) => sum + pipe.diameter / height, 0);
  const rawPhi = phiStruct + phiPipes;
  const phiTotal = Math.min(Math.max(rawPhi, 0.1), 1.0);

  // 2. Coeficiente de Arrasto Frontal (Ca) para o primeiro pórtico
  let caFrontal = 1.6;
  if (phiTotal <= 0.6) {
    caFrontal = linearInterp1D(PHI_ARRAY, CA_FLAT_ARRAY, phiTotal);
  } else {
    caFrontal = 1.6 - (phiTotal - 0.6) * 1.0; 
  }

  // 3. Fator de proteção (η) para pórticos a sotavento
  const eh = spacing / height;
  const eta = getEtaTable28(phiTotal, eh);

  // 4. Forças Lineares (kN/m)
  const effectiveAreaPerMeter = phiTotal * height;
  const linearLoadFront = q * effectiveAreaPerMeter * caFrontal;
  const linearLoadBack = linearLoadFront * eta;

  // 5. Força Global (kN)
  const totalLinearLoad = linearLoadFront + (numFrames > 1 ? linearLoadBack * (numFrames - 1) : 0);
  const globalForce = totalLinearLoad * width;

  return {
    phiTotal,
    caFrontal,
    eta,
    linearLoadFront,
    linearLoadBack,
    globalForce
  };
}
