{% extends "/base.html" %}
{% block title %}{{ result.target }} (ランク{{ result.rank }}) - Nercone TLS Test{% endblock %}
{% block title_suffix %}TLS Test{% endblock %}
{% block description %}Nercone TLS Test の結果ページです。対象: {{ result.target }} / スコア: {{ "%.1f"|format(result.score or 0) }} / ランク: {{ result.rank }}。{% endblock %}
{% block header_desc %}ただのTLS/SSL設定分析サービス{% endblock %}
{% block extra_head %}
        <link rel="stylesheet" href="/tools/tls-test/assets/tls-test.css">
{% endblock %}

{# ------------------------------------------------------------------
   Replace the site header with a results banner that carries the rank
   badge, target, metadata, action buttons, and the tab bar at its foot.
   ------------------------------------------------------------------ #}
{% block custom_header %}
            {% set rank_color_map = {
                'SSS': 'bright-green', 'SS': 'bright-green', 'S': 'bright-green',
                'A': 'green', 'B': 'green', 'C': 'green',
                'D': 'bright-yellow', 'E': 'bright-yellow', 'F': 'bright-yellow',
                'G': 'yellow', 'H': 'yellow', 'I': 'yellow',
                'J': 'bright-orange', 'K': 'bright-orange', 'L': 'bright-orange',
                'M': 'orange', 'N': 'orange',
                'O': 'bright-red', 'P': 'bright-red',
                'Q': 'red', 'R': 'bright-purple'
            } %}
            {% set rank = result.rank or job.rank or '?' %}
            {% set rank_color = rank_color_map.get(rank, 'tx') %}

            <header class="tls-results-header">
                <div class="tls-results-head">
                    <div class="tls-rank-badge text-{{ rank_color }}" aria-label="ランク {{ rank }}, スコア {{ '%.0f'|format(result.score or job.score or 0) }}">
                        <span class="tls-rank-letters">{{ rank }}</span>
                        <span class="tls-rank-score">{{ "%.0f"|format(result.score or job.score or 0) }}</span>
                    </div>
                    <div class="tls-results-meta flex-1">
                        <h1 class="tls-results-target">{{ result.target or job.target }}</h1>
                        <p class="tls-results-metaline">
                            <span class="text-tx-alt">実行日時</span>
                            <span>{{ finished_at_display or job.finished_at or "—" }}</span>
                            <span class="text-tx-alt">所要時間</span>
                            <span>{{ "%.0f"|format((result.duration or 0) * 1000) }}ms</span>
                        </p>
                        <p class="tls-results-testid"><code class="text-tx-alt">{{ test_id }}</code></p>
                        {% if result.error %}
                        <p class="text-bright-red">{{ result.error }}</p>
                        {% endif %}
                    </div>
                    <div class="tls-results-actions">
                        <button type="button" class="tls-btn tls-btn-secondary" id="tls-print-pdf">PDFをダウンロード</button>
                        <button type="button" class="tls-btn tls-btn-primary" id="tls-copy-link" data-link="{{ share_url }}">リンクをコピー</button>
                    </div>
                </div>
                <nav class="tls-tabs" role="tablist">
                    <button type="button" class="tls-tab is-active" data-tab="summary" role="tab" aria-selected="true">概要</button>
                    <button type="button" class="tls-tab" data-tab="reliability" role="tab" aria-selected="false">信頼性</button>
                    <button type="button" class="tls-tab" data-tab="safety" role="tab" aria-selected="false">安全性</button>
                    <button type="button" class="tls-tab" data-tab="vulnerabilities" role="tab" aria-selected="false">脆弱性</button>
                    <button type="button" class="tls-tab" data-tab="compatibility" role="tab" aria-selected="false">互換性</button>
                    <button type="button" class="tls-tab" data-tab="log" role="tab" aria-selected="false">ログ</button>
                    <button type="button" class="tls-tab" data-tab="history" role="tab" aria-selected="false">テスト履歴</button>
                    <button type="button" class="tls-tab" data-tab="json" role="tab" aria-selected="false">JSON</button>
                </nav>
            </header>
{% endblock %}

{% block content %}
            {#
                Log row for a finding. Columns:
                    [step]           severity-label + title(white)   detail(gray)
            #}
            {% macro finding_row(f) -%}
                <div class="tls-log-row">
                    <span class="tls-log-cat text-tx-alt">[{{ (f.step or f.group or f.category or 'info')|replace('_','-')|lower }}]</span>
                    <span class="tls-log-msg">
                        <span class="text-{{ f.color }} font-bold">{{ f.severity_label|upper }}</span>
                        <span class="text-tx">{{ f.title }}</span>
                    </span>
                    <span class="tls-log-detail text-tx-alt">{{ f.detail or '' }}</span>
                </div>
            {%- endmacro %}

            {# A boolean row rendered with green/red text. #}
            {% macro yn(value, ok='対応', bad='未対応') -%}
                {% if value %}<span class="text-bright-green">{{ ok }}</span>{% else %}<span class="text-bright-red">{{ bad }}</span>{% endif %}
            {%- endmacro %}

            {# Revocation cell (OCSP / CRL). Translates the technical error
               strings from certs/revocation.py into a single clean Japanese
               label, so we never print awkward combinations like
               「未確認 no OCSP URL」. #}
            {% macro rev_cell(r, kind) -%}
                {%- if not r -%}
                    <span class="text-tx-alt">—</span>
                {%- elif r.checked and not r.revoked -%}
                    <span class="text-bright-green">失効していません</span>
                    {%- if r.source %} <span class="font-small text-tx-alt">({{ r.source }})</span>{% endif -%}
                {%- elif r.checked and r.revoked -%}
                    <span class="text-bright-red">失効しています</span>
                    {%- if r.reason %} <span class="font-small text-tx-alt">({{ r.reason }})</span>{% endif -%}
                {%- else -%}
                    {%- set err = (r.error or '')|string -%}
                    {%- if 'no OCSP URL' in err or 'no AIA' in err -%}
                        <span class="text-tx-alt">{{ kind }} URL が提供されていません</span>
                    {%- elif 'no CRL DP' in err or 'no http CRL URL' in err -%}
                        <span class="text-tx-alt">{{ kind }} URL が提供されていません</span>
                    {%- elif 'all CRLs unreachable' in err -%}
                        <span class="text-bright-yellow">{{ kind }} レスポンダに到達できません</span>
                    {%- elif err -%}
                        <span class="text-bright-yellow">確認失敗</span>
                        <span class="font-small text-tx-alt">({{ err }})</span>
                    {%- else -%}
                        <span class="text-tx-alt">未確認</span>
                    {%- endif -%}
                {%- endif -%}
            {%- endmacro %}

            <div class="tls-tab-panels">

                {# -------- 概要 -------- #}
                <div class="tls-tab-panel is-active" data-panel="summary">
                    <div class="tls-log">
                        {% if summary %}
                            {% for f in summary %}{{ finding_row(f) }}{% endfor %}
                        {% else %}
                            <div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">該当項目なし</span></div>
                        {% endif %}
                    </div>
                </div>

                {# -------- 信頼性 -------- #}
                <div class="tls-tab-panel" data-panel="reliability">
                    {# Certificate chain table #}
                    {% set chain = result.data.certificate_chain if result.data else [] %}
                    {% if chain %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">証明書チェーン</h2>
                        <table class="tls-table">
                            <thead><tr>
                                <th>#</th><th>CN / Subject</th><th>発行者</th><th>有効期限</th><th>署名</th><th>鍵</th>
                            </tr></thead>
                            <tbody>
                                {% for c in chain %}
                                <tr>
                                    <td class="text-tx-alt">{{ loop.index }}</td>
                                    <td>
                                        <div>{{ c.common_name or c.subject or '—' }}</div>
                                        {% if c.sans %}<div class="font-small text-tx-alt">SAN: {{ (c.sans or [])|join(', ') }}</div>{% endif %}
                                    </td>
                                    <td>{{ c.issuer or '—' }}</td>
                                    <td>
                                        <div>{{ c.not_after or '—' }}</div>
                                        {% if c.is_expired %}<span class="text-bright-red font-bold">期限切れ</span>
                                        {% elif c.days_until_expiry is defined and c.days_until_expiry is not none %}<span class="font-small text-tx-alt">残 {{ c.days_until_expiry }} 日</span>{% endif %}
                                    </td>
                                    <td>{{ (c.signature_hash_algorithm or '—')|upper }}</td>
                                    <td>
                                        {{ c.public_key_algorithm or '—' }}{% if c.public_key_size_bits %} {{ c.public_key_size_bits }}-bit{% endif %}
                                        {% if c.public_key_curve %}<span class="font-small text-tx-alt"> ({{ c.public_key_curve }})</span>{% endif %}
                                    </td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </section>
                    {% endif %}

                    {# Trust stores #}
                    {% set trust = result.data.trust if result.data else [] %}
                    {% if trust %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">プラットフォームごとの信頼状況</h2>
                        <table class="tls-table">
                            <thead><tr><th>プラットフォーム</th><th>信頼</th><th>状況</th></tr></thead>
                            <tbody>
                                {% for t in trust %}
                                <tr>
                                    <td>{{ t.platform }}</td>
                                    <td>{{ yn(t.trusted, '信頼', '未信頼') }}</td>
                                    <td class="text-tx-alt">{{ t.error or '—' }}</td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </section>
                    {% endif %}

                    {# Revocation + HSTS + CAA summary #}
                    {% set ocsp = (result.data or {}).get('ocsp') %}
                    {% set crl = (result.data or {}).get('crl') %}
                    {% set hsts = (result.data or {}).get('hsts') %}
                    {% set caa = (result.data or {}).get('caa') %}
                    {% set preload = (result.data or {}).get('preload') %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">失効・HSTS・CAA</h2>
                        <table class="tls-table">
                            <tbody>
                                <tr><th>OCSP</th><td>{{ rev_cell(ocsp, 'OCSP') }}</td></tr>
                                <tr><th>CRL</th><td>{{ rev_cell(crl, 'CRL') }}</td></tr>
                                <tr><th>HSTS</th><td>
                                    {%- if not hsts or hsts.error -%}
                                        <span class="text-tx-alt">—</span>
                                    {%- elif hsts.present -%}
                                        <span class="text-bright-green">有効</span>
                                        <span class="font-small text-tx-alt">max-age={{ hsts.max_age }}{% if hsts.include_subdomains %}; includeSubDomains{% endif %}{% if hsts.preload %}; preload{% endif %}</span>
                                    {%- else -%}
                                        <span class="text-bright-red">無効</span>
                                    {%- endif -%}
                                </td></tr>
                                <tr><th>HSTS preload</th><td>
                                    {%- if preload -%}
                                        {%- for p in preload -%}
                                            <span class="font-small">{{ p.browser }}: {% if p.error %}<span class="text-tx-alt">取得エラー</span>{% else %}{{ yn(p.listed, 'Listed', 'Not listed') }}{% endif %}</span>{% if not loop.last %} · {% endif %}
                                        {%- endfor -%}
                                    {%- else -%}
                                        <span class="text-tx-alt">—</span>
                                    {%- endif -%}
                                </td></tr>
                                <tr><th>CAA</th><td>
                                    {%- if not caa -%}
                                        <span class="text-tx-alt">—</span>
                                    {%- elif caa.records -%}
                                        <span class="text-bright-green">{{ caa.records|length }} 件</span>
                                        <span class="font-small text-tx-alt">({{ caa.effective_host }})</span>
                                        <div class="font-small text-tx-alt">{{ caa.records|join('; ') }}</div>
                                    {%- else -%}
                                        <span class="text-bright-yellow">未設定</span>
                                    {%- endif -%}
                                </td></tr>
                            </tbody>
                        </table>
                    </section>

                    <section class="tls-section">
                        <h2 class="tls-section-title">信頼性に関するすべてのログ</h2>
                        <div class="tls-log">
                            {% set findings = groups['reliability'] %}
                            {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %}
                            {% else %}<div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">項目なし</span></div>{% endif %}
                        </div>
                    </section>
                </div>

                {# -------- 安全性 -------- #}
                <div class="tls-tab-panel" data-panel="safety">
                    {# Protocol versions #}
                    {% set versions = (result.data or {}).get('versions') %}
                    {% if versions %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">対応プロトコル</h2>
                        <table class="tls-table">
                            <thead><tr><th>バージョン</th><th>対応</th></tr></thead>
                            <tbody>
                                {% for name, ok in versions.items() %}
                                <tr><td>{{ name }}</td><td>{{ yn(ok, '有効', '無効') }}</td></tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </section>
                    {% endif %}

                    {# Accepted ciphers per version #}
                    {% set ciphers = (result.data or {}).get('ciphers') %}
                    {% if ciphers %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">受理された暗号スイート</h2>
                        {% for name, cs in ciphers.items() %}
                            {% if cs %}
                            <div class="tls-cipher-block">
                                <h3 class="tls-cipher-version">{{ name }} <span class="font-small text-tx-alt">({{ cs|length }})</span></h3>
                                <ul class="tls-cipher-list">
                                    {% for c in cs %}
                                        <li><code>{{ c }}</code></li>
                                    {% endfor %}
                                </ul>
                            </div>
                            {% endif %}
                        {% endfor %}
                    </section>
                    {% endif %}

                    {# Named groups #}
                    {% set groups_list = (result.data or {}).get('named_groups') %}
                    {% if groups_list %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">TLS 1.3 鍵交換グループ</h2>
                        <p>{% for g in groups_list %}<code>{{ g }}</code>{% if not loop.last %}, {% endif %}{% endfor %}</p>
                    </section>
                    {% endif %}

                    <section class="tls-section">
                        <h2 class="tls-section-title">安全性に関するすべてのログ</h2>
                        <div class="tls-log">
                            {% set findings = groups['safety'] %}
                            {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %}
                            {% else %}<div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">項目なし</span></div>{% endif %}
                        </div>
                    </section>
                </div>

                {# -------- 脆弱性 -------- #}
                <div class="tls-tab-panel" data-panel="vulnerabilities">
                    {% set hb = (result.data or {}).get('heartbleed') %}
                    {% set ccs = (result.data or {}).get('ccs_injection') %}
                    {% set renego = (result.data or {}).get('secure_renegotiation') %}
                    {% set scsv = (result.data or {}).get('fallback_scsv') %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">既知脆弱性の判定</h2>
                        <table class="tls-table">
                            <thead><tr><th>脆弱性</th><th>判定</th><th>詳細</th></tr></thead>
                            <tbody>
                                <tr><td>Heartbleed</td><td>{% if hb %}{{ yn(not hb.vulnerable, '影響なし', '影響あり') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td><td class="text-tx-alt">{% if hb %}{% if hb.heartbeat_extension %}Heartbeat advertised{% endif %}{% if hb.error %} {{ hb.error }}{% endif %}{% endif %}</td></tr>
                                <tr><td>CCS Injection</td><td>{% if ccs %}{{ yn(not ccs.vulnerable, '影響なし', '影響あり') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td><td class="text-tx-alt">{{ (ccs or {}).get('detail','') }}</td></tr>
                                <tr><td>Secure Renegotiation</td><td>{% if renego %}{{ yn(renego.supported, '対応', '未対応') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td><td class="text-tx-alt">{{ (renego or {}).get('detail','') }}</td></tr>
                                <tr><td>TLS_FALLBACK_SCSV</td><td>{% if scsv %}{{ yn(scsv.supported, '対応', '未対応') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td><td class="text-tx-alt">{{ (scsv or {}).get('detail','') }}</td></tr>
                            </tbody>
                        </table>
                    </section>

                    <section class="tls-section">
                        <h2 class="tls-section-title">脆弱性に関するすべてのログ</h2>
                        <div class="tls-log">
                            {% set findings = groups['vulnerabilities'] %}
                            {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %}
                            {% else %}<div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">項目なし</span></div>{% endif %}
                        </div>
                    </section>
                </div>

                {# -------- 互換性 -------- #}
                <div class="tls-tab-panel" data-panel="compatibility">
                    {% set http = (result.data or {}).get('http') %}
                    {% set http3 = (result.data or {}).get('http3') %}
                    {% set alpn = (result.data or {}).get('alpn') %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">HTTP プロトコル対応</h2>
                        <table class="tls-table">
                            <tbody>
                                <tr><th>HTTP/1.1</th><td>{% if http %}{{ yn(http.http1, '対応', '未対応') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td></tr>
                                <tr><th>HTTP/2</th><td>{% if http %}{{ yn(http.http2, '対応', '未対応') }}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td></tr>
                                <tr><th>HTTP/3 (QUIC)</th><td>{% if http3 %}{{ yn(http3.supported, '対応', '未対応') }}{% if http3.error %} <span class="font-small text-tx-alt">{{ http3.error }}</span>{% endif %}{% else %}<span class="text-tx-alt">—</span>{% endif %}</td></tr>
                                <tr><th>ALPN</th><td>{% if alpn %}<code>{{ alpn }}</code>{% else %}<span class="text-tx-alt">—</span>{% endif %}</td></tr>
                                {% if http and http.server %}<tr><th>Server</th><td><code>{{ http.server }}</code></td></tr>{% endif %}
                                {% if http and http.alt_svc %}<tr><th>Alt-Svc</th><td><code>{{ http.alt_svc }}</code></td></tr>{% endif %}
                            </tbody>
                        </table>
                    </section>

                    {% set sim = (result.data or {}).get('handshake_simulation') %}
                    {% if sim %}
                    <section class="tls-section">
                        <h2 class="tls-section-title">ハンドシェイクシミュレーション</h2>
                        <table class="tls-table">
                            <thead><tr><th>クライアント</th><th>結果</th><th>プロトコル</th><th>暗号</th><th>備考</th></tr></thead>
                            <tbody>
                                {% for s in sim %}
                                <tr>
                                    <td>{{ s.client }}</td>
                                    <td>{{ yn(s.connected, 'OK', 'Fail') }}</td>
                                    <td>{{ s.negotiated_version or '—' }}</td>
                                    <td><code class="font-small">{{ s.negotiated_cipher or '—' }}</code></td>
                                    <td class="font-small text-tx-alt">{{ s.error or '' }}</td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </section>
                    {% endif %}

                    <section class="tls-section">
                        <h2 class="tls-section-title">互換性に関するすべてのログ</h2>
                        <div class="tls-log">
                            {% set findings = groups['compatibility'] %}
                            {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %}
                            {% else %}<div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">項目なし</span></div>{% endif %}
                        </div>
                    </section>
                </div>

                {# -------- ログ --------
                   Replays the live processing log: interleaved progress rows
                   (from test_progress table) and findings (grouped by step). #}
                <div class="tls-tab-panel" data-panel="log">
                    <section class="tls-section">
                        <div class="tls-log tls-log-replay">
                            {% if log_entries %}
                                {% for e in log_entries %}
                                    {% if e.kind == 'phase' %}
                                        <div class="tls-log-row">
                                            <span class="tls-log-cat text-tx-alt">[{{ (e.phase or 'info')|replace('_','-')|lower }}]</span>
                                            <span class="tls-log-msg text-tx">{{ e.detail or '' }}</span>
                                            <span class="tls-log-detail text-tx-alt"></span>
                                        </div>
                                    {% else %}
                                        {{ finding_row(e.finding) }}
                                    {% endif %}
                                {% endfor %}
                            {% else %}
                                <div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">ログが記録されていません</span></div>
                            {% endif %}
                        </div>
                    </section>
                </div>

                {# -------- テスト履歴 -------- #}
                <div class="tls-tab-panel" data-panel="history">
                    <section class="tls-section">
                        <h2 class="tls-section-title">過去のテスト結果</h2>
                        {% if history %}
                        <table class="tls-table">
                            <thead><tr><th>実行日時</th><th>ランク</th><th>スコア</th><th>リンク</th></tr></thead>
                            <tbody>
                                {% for h in history %}
                                <tr>
                                    <td>{{ h.finished_at_display or '—' }}</td>
                                    <td>{{ h.rank or '—' }}</td>
                                    <td>{{ "%.0f"|format(h.score or 0) }}</td>
                                    <td><a href="/tools/tls-test/results/{{ h.id }}/" class="text-tx-alt">{{ h.id }}</a></td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                        {% else %}
                        <div class="tls-log-row"><span class="tls-log-cat text-tx-alt">[info]</span><span class="tls-log-msg text-tx-alt">過去のテスト結果はありません</span></div>
                        {% endif %}
                    </section>
                </div>

                {# -------- JSON -------- #}
                <div class="tls-tab-panel" data-panel="json">
                    <section class="tls-section">
                        <div class="tls-json-meta">
                            <code class="text-tx-alt">GET /api/tools/tls-test/results/{{ test_id }}</code>
                            <button type="button" class="tls-btn tls-btn-secondary" id="tls-copy-json">JSONをコピー</button>
                        </div>
                        <pre class="tls-raw" id="tls-raw-json"><code>{{ result | tojson(indent=2) }}</code></pre>
                    </section>
                </div>
            </div>

            <script src="/tools/tls-test/assets/tls-test-results.js" defer></script>
{% endblock %}
