/**
 * Exportação Ftool (.txt estruturado) — M9.4
 *
 * Gera um arquivo de texto com nós, barras e cargas lineares no
 * formato de importação do Ftool (software livre de análise de
 * pórticos planos 2D da PUC-Rio, amplamente usado em escritórios
 * brasileiros de cálculo estrutural).
 *
 * Convenção assumida:
 *  - Pórtico 2D no plano XY (eixo X horizontal, Y vertical)
 *  - Vento paralelo ao eixo X (de onde sopra)
 *  - Cargas distribuídas aplicadas no eixo Y local da barra
 *    (sinais: + empuxo de baixo p/ cima, − sucção de cima p/ baixo)
 *  - Unidades: kN e m
 *  - Pórtico típico com 4 colunas + 2 águas (cumeeira)
 *
 * Saída: arquivo `.txt` pronto para `File → Import` no Ftool.
 */

import { useGalpaoStore } from '../store/galpaoStore';
import { useWindStore } from '../store/appStore';
import {
  getColumnLinearLoads,
  getRoofLinearLoads,
} from './line-loads';

export interface FtoolNode {
  id: number;
  x: number;
  y: number;
}

export interface FtoolMember {
  id: number;
  nodeI: number;
  nodeJ: number;
  section: string;
  material: string;
}

export interface FtoolMemberLoad {
  memberId: number;
  /** Direção da carga: GlobalX ou GlobalY */
  direction: 'GlobalX' | 'GlobalY';
  /** Tipo de distribuição: Uniform, Point, Linear */
  type: 'Uniform' | 'Point' | 'Linear';
  /** Valor da carga (kN/m para Uniform, kN para Point) */
  value: number;
  /** Posição inicial (0..1) para Point/Linear */
  startPos?: number;
  /** Posição final (0..1) para Linear */
  endPos?: number;
}

export interface FtoolModel {
  units: { force: 'kN' | 'N' | 'kgf'; length: 'm' | 'cm' | 'mm' };
  materials: { id: number; name: string; eKpa: number; nu: number; rho: number }[];
  sections: { id: number; name: string; aM2: number; izM4: number }[];
  nodes: FtoolNode[];
  members: FtoolMember[];
  loadCases: { id: number; name: string; loads: FtoolMemberLoad[] }[];
}

/**
 * Gera o modelo do pórtico 2D do galpão a partir dos dados do store.
 *
 * Layout:
 *   N1 (0, 0)         N2 (b/2, h)         N3 (b, 0)
 *   |                 |                    |
 *   | coluna          | cumeeira           | coluna
 *   | barlavento      |                    | sotavento
 *   |                 |                    |
 *   N4 (0, h)         N5 (b/2, h+rise)     N6 (b, h)
 *
 * Para vento a 0° (largura perpendicular ao vento):
 *   - Colunas externas: 4 (vértices)
 *   - Colunas internas: 0
 *   - Cumeeira: 2 segmentos (água esquerda e direita)
 *
 * Para vento a 90° (comprimento perpendicular ao vento), o pórtico
 * efetivo vira — usamos o mesmo eixo X.
 */
export function buildFtoolModel(): FtoolModel {
  const galpao = useGalpaoStore.getState();
  const wind = useWindStore.getState();
  const { width: b, height: h, roofPitch, wallCpe, roofCpe } = galpao;
  const { q, cpi, windAngle } = wind;

  const FRAME_SPACING = 6.0;
  const PURLIN_SPACING = 1.5;

  const columnLoads = getColumnLinearLoads(cpi, q, wallCpe, FRAME_SPACING, windAngle);
  const roofLoads = getRoofLinearLoads(cpi, q, roofCpe, PURLIN_SPACING, roofPitch);

  const rise = (b / 2) * Math.tan((roofPitch * Math.PI) / 180);

  const nodes: FtoolNode[] = [
    { id: 1, x: 0, y: 0 },
    { id: 2, x: b / 2, y: h },
    { id: 3, x: b, y: 0 },
    { id: 4, x: 0, y: h },
    { id: 5, x: b / 2, y: h + rise },
    { id: 6, x: b, y: h },
  ];

  const members: FtoolMember[] = [
    { id: 1, nodeI: 1, nodeJ: 4, section: 'Coluna', material: 'Aco' },
    { id: 2, nodeI: 4, nodeJ: 5, section: 'TercaE', material: 'Aco' },
    { id: 3, nodeI: 5, nodeJ: 6, section: 'TercaD', material: 'Aco' },
    { id: 4, nodeI: 6, nodeJ: 3, section: 'Coluna', material: 'Aco' },
  ];

  const loadCaseWind: FtoolMemberLoad[] = [
    {
      memberId: 1,
      direction: 'GlobalX',
      type: 'Uniform',
      value: Number(columnLoads.windward.toFixed(4)),
    },
    {
      memberId: 4,
      direction: 'GlobalX',
      type: 'Uniform',
      value: Number(columnLoads.leeward.toFixed(4)),
    },
    {
      memberId: 2,
      direction: 'GlobalY',
      type: 'Uniform',
      value: Number(roofLoads.E.toFixed(4)),
    },
    {
      memberId: 3,
      direction: 'GlobalY',
      type: 'Uniform',
      value: Number(roofLoads.G.toFixed(4)),
    },
  ];

  return {
    units: { force: 'kN', length: 'm' },
    materials: [
      { id: 1, name: 'Aco', eKpa: 2.0e8, nu: 0.3, rho: 78.5 },
    ],
    sections: [
      { id: 1, name: 'Coluna', aM2: 0.005, izM4: 0.0001 },
      { id: 2, name: 'TercaE', aM2: 0.002, izM4: 0.00003 },
      { id: 3, name: 'TercaD', aM2: 0.002, izM4: 0.00003 },
    ],
    nodes,
    members,
    loadCases: [
      {
        id: 1,
        name: `Vento ${windAngle}° (q=${q.toFixed(3)} kN/m², Cpi=${cpi.toFixed(2)})`,
        loads: loadCaseWind,
      },
    ],
  };
}

/**
 * Serializa o modelo Ftool em texto compatível com File → Import do Ftool.
 *
 * Formato de saída (Ftool ASCII):
 *   - Seções em blocos com palavra-chave de abertura e End.
 *   - Linhas com `Id valor X valor Y valor` para dados tabulares.
 */
export function serializeFtool(model: FtoolModel): string {
  const lines: string[] = [];

  lines.push('; =============================================');
  lines.push('; VentoApp — Modelo Ftool');
  lines.push(`; Gerado em: ${new Date().toISOString()}`);
  lines.push('; NBR 6123:2023 — Forças devidas ao vento');
  lines.push('; =============================================');
  lines.push('');
  lines.push('GENERAL');
  lines.push(`Units ${model.units.force} ${model.units.length}`);
  lines.push('EndGENERAL');
  lines.push('');

  lines.push('MATERIAL');
  model.materials.forEach((m) => {
    lines.push(`Id ${m.id}`);
    lines.push(`Name "${m.name}"`);
    lines.push(`E ${m.eKpa.toExponential(6)}`);
    lines.push(`Nu ${m.nu}`);
    if (m.rho > 0) lines.push(`Rho ${m.rho}`);
    lines.push('EndMATERIAL');
  });
  lines.push('');

  lines.push('SECTION');
  model.sections.forEach((s) => {
    lines.push(`Id ${s.id}`);
    lines.push(`Name "${s.name}"`);
    lines.push(`A ${s.aM2.toExponential(6)}`);
    lines.push(`Iz ${s.izM4.toExponential(6)}`);
    lines.push('EndSECTION');
  });
  lines.push('');

  lines.push('NODE');
  model.nodes.forEach((n) => {
    lines.push(`Id ${n.id} X ${fmt(n.x)} Y ${fmt(n.y)}`);
  });
  lines.push('EndNODE');
  lines.push('');

  const sectionNameById = new Map(model.sections.map((s) => [s.name, s.id]));
  const materialNameById = new Map(model.materials.map((m) => [m.name, m.id]));

  lines.push('MEMBER');
  model.members.forEach((m) => {
    const secId = sectionNameById.get(m.section) ?? 1;
    const matId = materialNameById.get(m.material) ?? 1;
    lines.push(
      `Id ${m.id} NodeI ${m.nodeI} NodeJ ${m.nodeJ} SectionId ${secId} MaterialId ${matId}`,
    );
  });
  lines.push('EndMEMBER');
  lines.push('');

  model.loadCases.forEach((lc) => {
    lines.push('LOADCASE');
    lines.push(`Id ${lc.id}`);
    lines.push(`Name "${lc.name}"`);
    lines.push('MEMBERLOAD');
    lc.loads.forEach((load) => {
      if (load.type === 'Uniform') {
        lines.push(
          `MemberId ${load.memberId} Dir ${load.direction} Type Uniform Value ${fmt(load.value, 4)}`,
        );
      } else if (load.type === 'Point') {
        lines.push(
          `MemberId ${load.memberId} Dir ${load.direction} Type Point Pos ${fmt(load.startPos ?? 0.5)} Value ${fmt(load.value, 4)}`,
        );
      } else if (load.type === 'Linear') {
        lines.push(
          `MemberId ${load.memberId} Dir ${load.direction} Type Linear PosIni ${fmt(load.startPos ?? 0)} PosFim ${fmt(load.endPos ?? 1)} ValueIni ${fmt(load.value, 4)} ValueFim ${fmt(load.value, 4)}`,
        );
      }
    });
    lines.push('EndMEMBERLOAD');
    lines.push('EndLOADCASE');
  });

  return lines.join('\n') + '\n';
}

function fmt(n: number, decimals = 4): string {
  if (!Number.isFinite(n)) return '0';
  if (n === 0) return '0';
  return n.toFixed(decimals).replace(/\.?0+$/, '');
}

/**
 * Exporta o modelo atual como arquivo .txt compatível com Ftool.
 *
 * Cria um Blob com o conteúdo serializado e dispara download automático.
 */
export function exportGalpaoToFtool(): void {
  const model = buildFtoolModel();
  const content = serializeFtool(model);

  const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.setAttribute('href', url);
  link.setAttribute('download', 'galpao_ftool.ftl');
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}