/**
 * Coeficientes de força de atrito — NBR 6123:2023, sec. 6.1.5
 *
 * Para edificações correntes de planta retangular, a força de atrito
 * deve ser considerada somente quando l₀/h ou l₀/b > 4.
 *
 * F_f = C_f · q · [A_roof + A_walls_paralelas]
 *
 * C_f = 0,01 (sem nervuras); 0,02 (nervuras arredondadas);
 *      0,04 (nervuras retangulares).
 */

export type SurfaceRoughness = 'smooth' | 'rounded-ribs' | 'rectangular-ribs';

export const FRICTION_CF: Readonly<Record<SurfaceRoughness, number>> = {
  smooth: 0.01,
  'rounded-ribs': 0.02,
  'rectangular-ribs': 0.04,
};

export interface FrictionInput {
  roughness: SurfaceRoughness;
  /** Comprimento l0 da estrutura (m) */
  length: number;
  /** Altura h */
  height: number;
  /** Largura b */
  width: number;
  /** Inclinação do telhado (graus) */
  roofPitch: number;
  /** Pressão dinâmica q em kN/m² */
  q: number;
}

export interface FrictionResult {
  /** true se a condição l0/h > 4 ou l0/b > 4 foi atendida */
  applies: boolean;
  /** Área do telhado (m²) — depende do tipo de telhado */
  roofArea: number;
  /** Área das paredes paralelas ao vento (m²) */
  wallsArea: number;
  /** Cf usado */
  cf: number;
  /** Força de atrito total (kN) */
  forceKN: number;
}

/** Calcula a área do telhado em função da geometria (galpão retangular) */
export function roofArea(a: number, b: number, pitchDeg: number): number {
  const theta = (pitchDeg * Math.PI) / 180;
  const slantHalf = (b / 2) / Math.cos(theta);
  return 2 * slantHalf * a;
}

export function calculateFriction(input: FrictionInput): FrictionResult {
  const ratioLh = input.length / input.height;
  const ratioLb = input.length / input.width;
  const applies = ratioLh > 4 || ratioLb > 4;
  const cf = FRICTION_CF[input.roughness];

  if (!applies) {
    return { applies, roofArea: 0, wallsArea: 0, cf, forceKN: 0 };
  }

  const roofAreaM2 = roofArea(input.length, input.width, input.roofPitch);
  const roofSlant = roofAreaM2;

  const theta = (input.roofPitch * Math.PI) / 180;
  const wallHeightFull = input.height + (input.width / 2) * Math.tan(theta);
  const wallAreaUpwind = wallHeightFull * input.length;
  const wallAreaDownwind = wallHeightFull * input.length;
  const totalArea = roofSlant + wallAreaUpwind + wallAreaDownwind;

  const forceKN = cf * input.q * totalArea;

  return {
    applies,
    roofArea: roofSlant,
    wallsArea: wallAreaUpwind + wallAreaDownwind,
    cf,
    forceKN: Number(forceKN.toFixed(3)),
  };
}