{% extends "base.html" %}
{% block title %}Beam Moment Capacity - ConcreteDesignPy{% endblock %}

{% block head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@14/dist/handsontable.full.min.css">
<script src="https://cdn.jsdelivr.net/npm/handsontable@14/dist/handsontable.full.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/plotly.js-dist-min/plotly.min.js"></script>
<style>
.beam-page-layout { display: flex; gap: 2rem; align-items: flex-start; }
.beam-page-left { flex: 0 0 480px; }
.beam-page-right { flex: 1; min-width: 0; }
.beam-page-right .results-panel { position: sticky; top: 1rem; }
.report-full { margin-top: 1.5rem; }
.report-section {
    background: #fff; border: 1px solid var(--gray-200);
    border-radius: var(--radius); padding: 1.25rem; margin-bottom: 1rem;
}
.report-section h4 {
    font-size: .95rem; color: var(--primary-dark); margin: 0 0 .75rem;
    padding-bottom: .35rem; border-bottom: 2px solid var(--primary-light);
}
.report-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .3rem 2rem; font-size: .85rem; }
.report-grid dt { color: var(--gray-500); }
.report-grid dd { font-family: "SF Mono","Fira Code",monospace; font-weight: 500; text-align: right; }
.report-eq { background: var(--gray-50); padding: .6rem 1rem; border-radius: 4px; margin: .5rem 0; font-size: .9rem; }
.report-table {
    width: 100%; border-collapse: collapse; font-size: .8rem; margin: .5rem 0;
}
.report-table th {
    background: var(--primary-dark); color: #fff; padding: .35rem .5rem;
    text-align: center; font-weight: 600; font-size: .75rem;
}
.report-table td {
    padding: .3rem .5rem; text-align: center; border-bottom: 1px solid var(--gray-200);
    font-family: "SF Mono","Fira Code",monospace; font-size: .78rem;
}
.report-table tr:nth-child(even) { background: var(--gray-50); }
.report-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.iter-table-wrap { max-height: 400px; overflow-y: auto; border: 1px solid var(--gray-200); border-radius: 4px; }
</style>
{% endblock %}

{% block content %}
<div class="calc-page">
    <a href="/" class="back-link">&larr; All Calculators</a>
    <h1>Beam Flexural Capacity &mdash; Strain Compatibility Method</h1>
    <p class="ref">NSCP 2015 / ACI 318-19</p>

    <div class="beam-page-layout">
        <div class="beam-page-left">
            <form id="calc-form" class="calc-form">
                <div class="form-section">
                    <h3>Materials</h3>
                    <div class="form-row">
                        <div class="form-group"><label>f'c (MPa)</label><input type="number" name="fc" value="20.68" step="0.01" required></div>
                        <div class="form-group"><label>fy (MPa)</label><input type="number" name="fy" value="414" step="0.01" required></div>
                        <div class="form-group"><label>Es (MPa)</label><input type="number" name="es" value="200000" step="1"></div>
                    </div>
                </div>

                <div class="form-section">
                    <h3>Section Properties</h3>
                    <div class="form-row">
                        <div class="form-group"><label>Width, b (mm)</label><input type="number" id="beam-b" name="b" value="500" step="1" required></div>
                        <div class="form-group"><label>Height, h (mm)</label><input type="number" id="beam-h" name="h" value="800" step="1" required></div>
                    </div>
                </div>

                <div class="form-section">
                    <h3>Reinforcement</h3>
                    <div id="rebar-table" style="width:100%;overflow:hidden;"></div>
                    <button type="button" class="btn-secondary" onclick="addRebarRow()">+ Add Rebar Layer</button>
                </div>

                <button type="submit" class="btn-primary" style="width:100%;">Calculate</button>
            </form>
        </div>

        <div class="beam-page-right">
            <div id="results" class="results-panel" style="display:none;">
                <h2>Design Check</h2>
                <div id="results-svg" style="text-align:center;"></div>
                <div id="results-summary"></div>
            </div>
        </div>
    </div>

    <div id="results-report" class="report-full" style="display:none;"></div>
</div>

<script>
// ── Handsontable Rebar Table ──
var rebarData = [
    [62.5, 25, 2],
    [737.5, 25, 6],
    [null, null, null],
];
var rebarHot = new Handsontable(document.getElementById('rebar-table'), {
    data: rebarData,
    colHeaders: ['Depth, d (mm)', 'Diameter (mm)', 'Quantity'],
    columns: [
        { type: 'numeric', numericFormat: { pattern: '0.0' }, width: 120 },
        { type: 'numeric', numericFormat: { pattern: '0' }, width: 120 },
        { type: 'numeric', numericFormat: { pattern: '0' }, width: 80 },
    ],
    rowHeaders: false, minRows: 2, minSpareRows: 1,
    contextMenu: true, stretchH: 'all', height: 'auto',
    className: 'htCenter', licenseKey: 'non-commercial-and-evaluation',
});

function addRebarRow() {
    var h = parseFloat(document.getElementById('beam-h').value) || 800;
    rebarHot.alter('insert_row_below', rebarHot.countRows() - 1, 1);
    var row = rebarHot.countRows() - 2;
    rebarHot.setDataAtCell(row, 0, Math.round(h - 62.5));
    rebarHot.setDataAtCell(row, 1, 25);
    rebarHot.setDataAtCell(row, 2, 2);
}

function getRebarList() {
    var list = [], data = rebarHot.getData();
    for (var i = 0; i < data.length; i++) {
        var d = data[i][0], diam = data[i][1], num = data[i][2];
        if (d !== null && d !== '' && diam !== null && diam !== '' && num !== null && num !== '' && num > 0) {
            list.push({ d: parseFloat(d), diam: parseFloat(diam), num: parseInt(num) });
        }
    }
    return list;
}

// Submit
document.getElementById('calc-form').addEventListener('submit', function(e) {
    e.preventDefault();
    var rebar_list = getRebarList();
    if (rebar_list.length === 0) { alert('Add at least one rebar layer.'); return; }
    var payload = { fc: parseFloat(this.fc.value), fy: parseFloat(this.fy.value), es: parseFloat(this.es.value), b: parseFloat(this.b.value), h: parseFloat(this.h.value), rebar_list: rebar_list };

    submitCalc('/api/beam/moment', payload, function(result) {
        // Cross-section SVG
        document.getElementById('results-svg').innerHTML = result.svg || '';

        // Quick summary in sticky panel
        var r = result;
        var s = '<dl class="report-grid" style="font-size:.85rem;">';
        s += '<dt>Neutral Axis, c</dt><dd>' + r.neutral_axis + ' mm</dd>';
        s += '<dt>a = &beta;1 &times; c</dt><dd>' + r.a + ' mm</dd>';
        s += '<dt>&epsilon;t</dt><dd>' + r.epsilon_t + '</dd>';
        s += '<dt>&phi;</dt><dd>' + r.phi + ' (' + r.classification + ')</dd>';
        s += '<dt><b>Mn</b></dt><dd><b>' + r.mn + ' kN-m</b></dd>';
        s += '<dt><b>Mu = &phi;Mn</b></dt><dd><b>' + r.mu + ' kN-m</b></dd>';
        s += '</dl>';
        document.getElementById('results-summary').innerHTML = s;

        // ── Full Report (single container) ──
        var h = '<div class="report-section">';

        // Concrete Strain
        h += '<h4>Concrete Strain</h4>';
        h += '<div class="report-eq">\\[ \\epsilon_c = ' + r.ecu + ' \\]</div>';

        // Yield Steel Strain
        h += '<h4>Yield Steel Strain</h4>';
        h += '<div class="report-eq">\\[ \\epsilon_s = \\frac{f_y}{E_s} = \\frac{' + payload.fy.toFixed(2) + ' \\text{ MPa}}{' + payload.es.toFixed(2) + ' \\text{ MPa}} = ' + r.epsilon_ty + ' \\]</div>';

        // Beta1
        h += '<h4>Rectangular Compression Block Factor</h4>';
        h += '<p style="font-size:.85rem;color:var(--gray-500);">Reference: NSCP 2015 Section 422.2.2.4.3</p>';
        h += '<div class="report-eq">\\[ \\beta_1 = ' + r.beta1 + ' \\]</div>';

        // Reinforcement Data Pattern
        h += '<h4>Reinforcement Data Pattern</h4>';
        h += '<table class="report-table"><tr><th>d (mm)</th><th>d<sub>b</sub> (mm)</th><th>n</th><th>As (mm&sup2;)</th></tr>';
        if (r.rebar_pattern) {
            r.rebar_pattern.forEach(function(rb) {
                h += '<tr><td>' + rb.d + '</td><td>' + rb.diam + '</td><td>' + rb.n + '</td><td>' + rb.as_mm2 + '</td></tr>';
            });
        }
        h += '</table>';

        // Iteration Results Table
        if (r.iterations && r.iterations.length > 0) {
            h += '<h4>Iteration Results Table</h4>';
            h += '<div class="iter-table-wrap"><table class="report-table">';
            h += '<tr><th>Iteration</th><th>c (mm)</th><th>c/dt</th><th>F<sub>c</sub> (kN)</th><th>F<sub>t</sub> (kN)</th><th>F<sub>c</sub> + F<sub>t</sub> (kN)</th><th>F<sub>s</sub> (kN)</th><th>Ratio</th></tr>';
            r.iterations.forEach(function(it) {
                h += '<tr><td>' + it.iteration + '</td><td>' + it.c + '</td><td>' + it.c_dt + '</td>';
                h += '<td>' + it.fc_kn + '</td><td>' + it.ft_kn + '</td><td>' + it.fc_ft_kn + '</td>';
                h += '<td>' + it.fs_kn + '</td><td>' + it.ratio + '</td></tr>';
            });
            h += '</table></div>';
        }

        // Depth of Neutral Axis
        h += '<h4>Depth of Neutral Axis</h4>';
        h += '<div class="report-eq">\\[ c = ' + r.neutral_axis + ' \\text{ mm} \\]</div>';

        // Beam Cross-Section (SVG from server)
        h += '<h4>Beam Cross-Section (' + payload.b + ' mm x ' + payload.h + ' mm)</h4>';
        h += '<div style="text-align:center;">' + (result.svg || '') + '</div>';

        // Compression / Tension reinforcement tables
        var compBars = [], tensBars = [];
        if (r.rebar_pattern) {
            r.rebar_pattern.forEach(function(rb) {
                if (rb.d < payload.h / 2) compBars.push(rb); else tensBars.push(rb);
            });
        }
        if (compBars.length > 0) {
            h += '<p style="font-size:.85rem;font-weight:600;margin-top:1rem;">Compression Reinforcement</p>';
            h += '<table class="report-table"><tr><th>d (mm)</th><th>diam (mm)</th><th>n</th><th>As (mm&sup2;)</th></tr>';
            compBars.forEach(function(rb) { h += '<tr><td>' + rb.d + '</td><td>' + rb.diam + '</td><td>' + rb.n + '</td><td>' + rb.as_mm2 + '</td></tr>'; });
            h += '</table>';
        }
        if (tensBars.length > 0) {
            h += '<p style="font-size:.85rem;font-weight:600;margin-top:.5rem;">Tension Reinforcement</p>';
            h += '<table class="report-table"><tr><th>d (mm)</th><th>diam (mm)</th><th>n</th><th>As (mm&sup2;)</th></tr>';
            tensBars.forEach(function(rb) { h += '<tr><td>' + rb.d + '</td><td>' + rb.diam + '</td><td>' + rb.n + '</td><td>' + rb.as_mm2 + '</td></tr>'; });
            h += '</table>';
        }

        // Depth of equivalent rectangular stress block
        h += '<h4>Depth of Equivalent Rectangular Stress Block</h4>';
        h += '<div class="report-eq">\\[ a = \\beta_1 \\times c \\]</div>';
        h += '<div class="report-eq">\\[ a = ' + r.beta1 + ' \\times ' + r.neutral_axis + ' \\text{ mm} \\]</div>';
        h += '<div class="report-eq">\\[ \\mathbf{a = ' + r.a + ' \\text{ mm}} \\]</div>';

        // Actual Tension Strain
        h += '<h4>Actual Tension Strain in Reinforcement</h4>';
        h += '<div class="report-eq">\\[ \\epsilon_t = \\frac{d - c}{c} \\times \\epsilon_{cu} \\]</div>';
        h += '<div class="report-eq">\\[ \\epsilon_t = \\frac{' + r.d_max + ' - ' + r.neutral_axis + '}{' + r.neutral_axis + '} \\times ' + r.ecu + ' \\]</div>';
        h += '<div class="report-eq">\\[ \\mathbf{\\epsilon_t = ' + r.epsilon_t + '} \\]</div>';

        // Strength Reduction Factor Plot
        h += '<h4>Variation of &phi; with Net Tensile Strain &epsilon;<sub>t</sub></h4>';
        h += '<div id="phi-plot" style="width:100%;height:400px;"></div>';

        // Nominal Moment Capacity
        h += '<h4>Nominal Moment Capacity</h4>';
        h += '<div class="report-eq">\\[ M_n = F_c \\times \\left(d - \\frac{a}{2}\\right) + F_t \\left(d - d_c\\right) \\]</div>';
        if (r.rebar_forces) {
            h += '<table class="report-table"><tr><th>Layer</th><th>d (mm)</th><th>As (mm&sup2;)</th><th>&epsilon;s</th><th>fs (MPa)</th><th>Force (kN)</th></tr>';
            r.rebar_forces.forEach(function(rf, i) {
                h += '<tr><td>' + (i+1) + '</td><td>' + rf.d + '</td><td>' + rf.area + '</td>';
                h += '<td>' + rf.strain + '</td><td>' + rf.stress + '</td><td>' + rf.force + '</td></tr>';
            });
            h += '</table>';
        }
        h += '<div class="report-eq">\\[ \\mathbf{M_n = ' + r.mn + ' \\text{ kN-m}} \\]</div>';

        // Ultimate Moment Capacity
        h += '<h4>Ultimate Moment Capacity</h4>';
        h += '<p style="font-size:.85rem;">Classification: <b>' + r.classification + '</b></p>';
        h += '<div class="report-eq">\\[ M_u = \\phi \\times M_n \\]</div>';
        h += '<div class="report-eq">\\[ M_u = ' + r.phi + ' \\times ' + r.mn + ' \\text{ kN-m} \\]</div>';
        h += '<div class="report-eq" style="font-size:1.1rem;font-weight:700;background:#dcfce7;">\\[ \\mathbf{M_u = ' + r.mu + ' \\text{ kN-m}} \\]</div>';

        h += '</div>'; // close single report-section

        var reportDiv = document.getElementById('results-report');
        reportDiv.style.display = '';
        reportDiv.innerHTML = h;
        if (window.MathJax) MathJax.typeset();

        // Render phi plot with Plotly
        if (r.phi_plot) {
            var pp = r.phi_plot;
            var xMax = pp.epsilon_ty + 0.004;
            // Clamp actual epsilon marker to curve range for display
            var markerX = Math.min(pp.actual_epsilon, xMax);
            var phiUsed = pp.actual_phi_other;
            var traces = [
                {
                    x: pp.strains, y: pp.phi_spiral,
                    name: 'Spiral', mode: 'lines',
                    line: { color: 'blue', width: 2.5, dash: 'dash' },
                },
                {
                    x: pp.strains, y: pp.phi_other,
                    name: 'Other', mode: 'lines',
                    line: { color: 'orange', width: 2.5 },
                },
                {
                    x: [markerX, markerX],
                    y: [0.6, phiUsed],
                    name: 'Actual \u03b5\u209c', mode: 'lines',
                    line: { color: 'red', width: 2, dash: 'dot' },
                    showlegend: true,
                },
                {
                    x: [0, markerX],
                    y: [phiUsed, phiUsed],
                    name: '\u03c6 = ' + phiUsed.toFixed(4),
                    mode: 'lines',
                    line: { color: 'red', width: 2, dash: 'dot' },
                    showlegend: true,
                },
                {
                    x: [markerX], y: [phiUsed],
                    mode: 'markers',
                    marker: { color: 'red', size: 8 },
                    showlegend: false,
                },
            ];
            var layout = {
                title: 'Variation of \u03c6 with Net Tensile Strain \u03b5<sub>t</sub>',
                xaxis: { title: 'Net Tensile Strain (\u03b5t)', range: [0, xMax] },
                yaxis: { title: 'Strength Reduction Factor (\u03c6)', range: [0.6, 0.95] },
                showlegend: true,
            };
            Plotly.newPlot('phi-plot', traces, layout, { responsive: true });
        }
    });
});
</script>
{% endblock %}
