/**
 * Coeficientes de arrasto (Ca) para edificações de planta retangular
 * em vento de baixa e alta turbulência — NBR 6123:2023, sec. 6.1.2 e 6.1.3
 *
 * Implementação das Figuras 4 (baixa turbulência) e 5 (alta turbulência)
 * por meio de interpolação log-log dos dados extraídos da norma.
 *
 * Gráfico: Ca em função de h/l1 e l1/l2
 *  - h/l1: 0,25 / 0,5 / 1 / 2 / 4 / 8
 *  - l1/l2: 0,4 / 0,6 / 0,8 / 1,0
 */

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

const HL1 = [0.25, 0.5, 1, 2, 4, 8] as const;
const L1L2 = [0.4, 0.6, 0.8, 1.0] as const;

const CA_LOW: Record<number, Record<number, number>> = {
  0.25: { 0.4: 1.2, 0.6: 1.2, 0.8: 1.2, 1.0: 1.2 },
  0.5: { 0.4: 1.2, 0.6: 1.2, 0.8: 1.2, 1.0: 1.2 },
  1: { 0.4: 1.25, 0.6: 1.2, 0.8: 1.15, 1.0: 1.1 },
  2: { 0.4: 1.4, 0.6: 1.3, 0.8: 1.2, 1.0: 1.15 },
  4: { 0.4: 1.55, 0.6: 1.45, 0.8: 1.3, 1.0: 1.2 },
  8: { 0.4: 1.7, 0.6: 1.55, 0.8: 1.4, 1.0: 1.3 },
};

const CA_HIGH: Record<number, Record<number, number>> = {
  0.25: { 0.4: 1.0, 0.6: 1.0, 0.8: 1.0, 1.0: 1.0 },
  0.5: { 0.4: 1.0, 0.6: 1.0, 0.8: 1.0, 1.0: 1.0 },
  1: { 0.4: 1.05, 0.6: 1.0, 0.8: 0.95, 1.0: 0.9 },
  2: { 0.4: 1.2, 0.6: 1.1, 0.8: 1.0, 1.0: 0.95 },
  4: { 0.4: 1.35, 0.6: 1.25, 0.8: 1.1, 1.0: 1.0 },
  8: { 0.4: 1.5, 0.6: 1.35, 0.8: 1.2, 1.0: 1.1 },
};

function lookup(table: Record<number, Record<number, number>>, hl1: number, l1l2: number): number {
  const grid = {
    xs: L1L2,
    ys: HL1,
    values: HL1.map((h) => L1L2.map((l) => table[h][l])),
  };
  return bilinearInterp(grid, l1l2, hl1);
}

export type TurbulenceLevel = 'low' | 'high';

/**
 * Ca para vento de baixa ou alta turbulência.
 * @param l1 Dimensão da face atacada (largura perpendicular ao vento)
 * @param l2 Dimensão da face paralela ao vento (profundidade)
 * @param h Altura da edificação
 */
export function getDragCoefficient(
  l1: number,
  l2: number,
  h: number,
  turbulence: TurbulenceLevel = 'low',
): number {
  const hl1 = h / l1;
  const l1l2 = l1 / l2;
  const table = turbulence === 'high' ? CA_HIGH : CA_LOW;
  return Number(lookup(table, hl1, l1l2).toFixed(2));
}

/**
 * Requisitos para consideração de vento de alta turbulência (6.1.3.1):
 *  - Profundidade/largura > 1/3
 *  - Altura da edificação ≤ 2× altura média das vizinhanças
 *  - Distância mínima de vizinhança conforme altura:
 *      h ≤ 40 m:  500 m
 *      h ≤ 55 m:  1000 m
 *      h ≤ 70 m:  2000 m
 *      h ≤ 80 m:  3000 m
 *      h > 80 m:  não qualifica para alta turbulência por este critério
 */
export interface HighTurbulenceRequirementsInput {
  depth: number;
  width: number;
  height: number;
  neighborhoodHeightAvg: number;
  neighborhoodDistance: number;
}

export interface HighTurbulenceRequirementsResult {
  ok: boolean;
  reason: string[];
}

export function checkHighTurbulenceRequirements(
  input: HighTurbulenceRequirementsInput,
): HighTurbulenceRequirementsResult {
  const reason: string[] = [];
  const depthRatio = input.depth / input.width;
  if (depthRatio <= 1 / 3) reason.push(`Profundidade/largura (${depthRatio.toFixed(2)}) ≤ 1/3`);

  if (input.height > 2 * input.neighborhoodHeightAvg)
    reason.push(`Altura (${input.height}) > 2× altura média vizinhança (${input.neighborhoodHeightAvg})`);

  let requiredDistance = 0;
  if (input.height <= 40) requiredDistance = 500;
  else if (input.height <= 55) requiredDistance = 1000;
  else if (input.height <= 70) requiredDistance = 2000;
  else if (input.height <= 80) requiredDistance = 3000;
  else reason.push('Altura > 80 m não qualifica para alta turbulência');

  if (input.neighborhoodDistance < requiredDistance && requiredDistance > 0)
    reason.push(`Distância de vizinhança (${input.neighborhoodDistance} m) < ${requiredDistance} m`);

  return { ok: reason.length === 0, reason };
}