function describe_airperf_outputs(atm, base, CD0tot, T, cap, breg)
% DESCRIBE_AIRPERF_OUTPUTS  Imprime un resumen legible con unidades y significado.
% USO:
%   describe_airperf_outputs();                         % sin args -> calcula defaults
%   describe_airperf_outputs(atm, base, CD0tot, T, cap, breg);  % con tus structs

    % ---------- Soporte de defaults si faltan argumentos ----------
    if nargin < 6 || isempty(breg)
        % Defaults coherentes con el pipeline
        inputs.S   = 992.8; inputs.W=79600; inputs.AR=7.51; inputs.e=0.612;
        inputs.T_SL_tot=30858;
        inputs.h_ft=30000; inputs.M_cap=0.85;
        inputs.TSFC_nom=0.60; inputs.TSFC_bleed=0.608; inputs.use_bleed=true;
        inputs.LD_max=15.9; inputs.Wi_over_Wf=1.10;
        inputs.M_grid=(0.78:0.01:0.86)';

        atm   = isa_std_atmos(inputs.h_ft);
        base  = base_quantities(atm, inputs);
        CD0tot= build_CD0_total(inputs.M_grid, 0.0055, 0.0);
        T     = build_drag_table(inputs.M_grid, CD0tot, base, inputs);
        cap   = check_mach_cap(inputs.M_cap, CD0tot, base, inputs);
        breg  = breguet_ER(inputs, base, atm);
    end

    fprintf('\n================  RESUMEN DE SALIDAS  ================\n');

    % --- Atmósfera ---
    section_('Atmósfera (isa\\_std\\_atmos)');
    expl_('h_ft',  getf_(atm,'h_ft',NaN), 'ft',   'Altitud de cálculo');
    expl_('T_K',   atm.T_K,               'K',    'Temperatura absoluta (Kelvin)');
    expl_('T_R',   atm.T_R,               'R',    'Temperatura absoluta (Rankine)');
    expl_('a',     atm.a_fts,             'ft/s', 'Velocidad del sonido, a = sqrt(γ R T)');
    expl_('rho',   atm.rho,               'slug/ft^3','Densidad del aire');
    expl_('sigma', atm.sigma,             '-',    'Relación de densidad σ = ρ/ρ0 (escala T_{avail})');
    note_('Modelo usado: %s', getf_(atm,'model','(s/d)'));

    % --- Magnitudes base ---
    section_('Magnitudes base (base\\_quantities)');
    expl_('q0',    base.q0,   'lbf/ft^2','Presión dinámica a = 1; q = q0 M^2');
    expl_('q0S',   base.q0S,  'lbf',     'Producto q0 S (entra en D_{par}, C_L)');
    expl_('k',     base.k,    '-',       'Coef. inducido k = 1/(πAR e) (pondera k C_L^2)');
    expl_('TSFC',  base.TSFC, '1/hr',    'Consumo específico de empuje usado');

    % --- C_D0,total(M) ---
    section_('C_{D0,total}(M) (build\\_CD0\\_total)');
    note_('Malla: %d puntos de Mach (%.2f a %.2f)', numel(CD0tot.M), CD0tot.M(1), CD0tot.M(end));

    % --- Tabla D(M) ---
    section_('Tabla D(M) (build\\_drag\\_table)');
    note_('Columnas: M, C_{D0,tot}, C_D, C_L, D_{par}, D_{ind}, D_{tot} [lbf]');
    if ~isempty(T)
        [Dtmin,idx] = min(T.D_tot_lbf);
        note_('Mínimo D_{tot}: %.0f lbf @ M = %.2f', Dtmin, T.M(idx));
        printHead_(T, 6);
    end

    % --- Chequeo en M_cap ---
    section_('Chequeo @ M_{cap} (check\\_mach\\_cap)');
    expl_('CD_cap', cap.CD_cap, '-',   'C_D total en M_{cap}');
    expl_('D_cap',  cap.D_cap,  'lbf', 'Arrastre total en M_{cap}');
    expl_('T_avail',cap.T_avail,'lbf', 'Empuje disponible: T_{SL} · σ');
    note_('Condición gobernante: %s', cap.governing);

    % --- Breguet ---
    section_('Breguet (breguet\\_ER)');
    expl_('V', breg.V_kt, 'kt', 'Velocidad de crucero (V = M_{cap} · a)');
    expl_('E', breg.E_hr, 'h',  'Autonomía: E = (1/TSFC)(L/D) ln(W_i/W_f)');
    expl_('R', breg.R_nm, 'NM', 'Alcance:   R = V · E');

    fprintf('=======================================================\n\n');
end

% ============ helpers locales (nombres únicos para evitar conflictos) ============
function v = getf_(s,f,def)
    if isstruct(s) && isfield(s,f), v = s.(f); else, v = def; end
end
function section_(t), fprintf('\n--- %s ---\n', t); end
function note_(fmt, varargin), fprintf(['  ' fmt '\n'], varargin{:}); end
function expl_(symb,val,unit,txt)
    if isnumeric(val), sval=num2str(val,'%.5g'); else, sval=char(val); end
    fprintf('  %-8s = %-12s [%s]  %s\n', symb, sval, unit, txt);
end
function printHead_(Ti, n)
    n=min(n,height(Ti));
    fprintf('  %-5s | %-9s | %-8s | %-7s | %-10s | %-10s | %-10s\n', ...
        'M','CD0_tot','C_D','C_L','D_par','D_ind','D_tot');
    fprintf('  %s\n', repmat('-',1,72));
    for i=1:n
        fprintf('  %4.2f | %9.6f | %8.6f | %7.4f | %10.0f | %10.0f | %10.0f\n', ...
            Ti.M(i), Ti.CD0_tot(i), Ti.CD(i), Ti.CL(i), Ti.D_par_lbf(i), Ti.D_ind_lbf(i), Ti.D_tot_lbf(i));
    end
    if height(Ti) > n, fprintf('  ... (%d filas más)\n', height(Ti)-n); end
end



% ============================================================
%   AIRCRAFT PERFORMANCE & DESIGN – PIPELINE ASIGNACIONES 1–4
% ============================================================
%
% 🔹 Propósito
% Este conjunto de funciones automatiza los cálculos de 
% performance (Asignaciones 1–4), permitiendo trabajar tanto
% con CD0 base constante como con la curva ΔCD0(M) digitalizada.
% Los módulos están diseñados para ejecutarse en cadena y 
% generar tablas, gráficas y resúmenes con explicación.
%
% 🔹 Flujo de ejecución principal (pipeline)
%
% run_airperf.m
%   └─> isa_std_atmos     → atm
%   └─> base_quantities   → base
%   └─> build_CD0_total   → CD0tot
%   └─> build_drag_table  → T
%   └─> check_mach_cap    → cap
%   └─> breguet_ER        → breg
%   └─> describe_airperf_outputs(atm, base, CD0tot, T, cap, breg)
%
% 🔹 Descripción de cada módulo
%
% isa_std_atmos(h_ft)
%   ENTRADA: altitud [ft]
%   SALIDA : atm struct con:
%       T_K, T_R, a_fts, rho, sigma
%   → Modelo de atmósfera estándar (ISA).
%
% base_quantities(atm, inputs)
%   ENTRADA: atm, struct inputs con {S, W, AR, e, TSFC, T_SL_tot}
%   SALIDA : base struct con:
%       q0, q0S, k, TSFC corregido
%   → Calcula magnitudes base aerodinámicas.
%
% build_CD0_total(M_grid, CD0_base, dCD0)
%   ENTRADA: malla Mach, CD0_base, curva ΔCD0(M)
%   SALIDA : CD0tot vector
%   → Construye la curva de arrastre parasitario.
%     (dos caminos: CD0_base constante o digitalización ΔCD0).
%
% build_drag_table(M_grid, CD0tot, base, inputs)
%   ENTRADA: Mach grid, CD0tot, base, inputs
%   SALIDA : tabla T con columnas:
%       M, C_D0, C_D, C_L, D_par, D_ind, D_tot
%   → Calcula arrastres parasitario, inducido y total.
%
% check_mach_cap(M_cap, CD0tot, base, inputs)
%   ENTRADA: Mach operativo
%   SALIDA : cap struct con:
%       C_D_cap, D_cap, T_avail
%   → Compara empuje disponible vs arrastre.
%     Determina si gobierna Mach límite o empuje.
%
% breguet_ER(inputs, base, atm)
%   ENTRADA: TSFC, (L/D), Wi/Wf, Mach operativo
%   SALIDA : breg struct con:
%       E (endurance), R (range)
%   → Implementa ecuaciones de Breguet.
%
% describe_airperf_outputs(atm, base, CD0tot, T, cap, breg)
%   ENTRADA: todos los structs anteriores
%   SALIDA : impresión en consola con unidades y explicación
%   → Resume y documenta resultados.
%
% 🔹 Notas de uso
% - Siempre arrancar desde run_airperf.m
% - Cada módulo puede probarse aislado llamando con sus argumentos.
% - Diseñado para Matlab Online con entrada/salida clara y
%   documentada para reportes técnicos en LaTeX.
%
% ============================================================
