<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scan Analysis - Finite State Report</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            line-height: 1.6;
            color: #333;
            background-color: #f8f9fa;
        }
        
        .container {
            margin: 0 auto;
            padding: 20px;
            background-color: white;
            border: 1px solid #dee2e6;
            min-height: 100%;
        }
        
        .header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 2px solid #e9ecef;
        }
        
        .logo-container {
            margin-bottom: 20px;
        }
        
        .company-logo {
            max-height: 50px;
            width: auto;
            margin: 0 auto;
            display: block;
        }
        
        .header h1 {
            color: #2c3e50;
            font-size: 2.5em;
            margin-bottom: 10px;
        }
        
        .header .subtitle {
            color: #6c757d;
            font-size: 1.1em;
        }
        
        .metadata {
            background-color: #f8f9fa;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 30px;
            font-size: 0.9em;
            color: #6c757d;
        }
        
        .chart-container {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 30px;
            border: 1px solid #dee2e6;
        }
        
        .chart-wrapper {
            position: relative;
            height: 400px;
            margin: 20px 0;
        }
        
        .chart-title {
            color: #2c3e50;
            font-size: 1.5em;
            margin-bottom: 10px;
        }
        
        .chart-description {
            color: #6c757d;
            font-size: 0.95em;
            margin-bottom: 20px;
        }
        
        .summary-cards {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        
        .summary-card {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            border: 1px solid #dee2e6;
            text-align: center;
        }
        
        .summary-card h3 {
            color: #2c3e50;
            font-size: 1.2em;
            margin-bottom: 10px;
        }
        
        .summary-card .value {
            font-size: 2em;
            font-weight: bold;
            color: #007bff;
        }
        
        .summary-card .unit {
            color: #6c757d;
            font-size: 0.9em;
        }
        
        .table-container {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 30px;
            border: 1px solid #dee2e6;
        }
        
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }
        
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #dee2e6;
        }
        
        th {
            background-color: #f8f9fa;
            font-weight: 600;
            color: #495057;
        }
        
        tr:hover {
            background-color: #f8f9fa;
        }
        
        .footer {
            text-align: center;
            margin-top: 40px;
            padding-top: 20px;
            border-top: 1px solid #e9ecef;
            color: #6c757d;
            font-size: 0.9em;
        }
        
        .finite-state-logo {
            color: #007bff;
            font-weight: bold;
        }
        
        .success-rate {
            font-weight: bold;
        }
        
        .success-rate.high { color: #28a745; }
        .success-rate.medium { color: #ffc107; }
        .success-rate.low { color: #dc3545; }
        
        .no-data {
            text-align: center;
            color: #6c757d;
            font-style: italic;
            padding: 40px;
        }
        
        .status-badge, .type-badge {
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 0.8em;
            font-weight: 600;
            text-transform: uppercase;
        }
        
        .status-completed { background-color: #d4edda; color: #155724; }
        .status-error { background-color: #f8d7da; color: #721c24; }
        .status-initial { background-color: #d1ecf1; color: #0c5460; }
        .status-started { background-color: #fff3cd; color: #856404; }
        
        .type-sca { background-color: #e2e3f3; color: #383d41; }
        .type-sast { background-color: #d4edda; color: #155724; }
        .type-config { background-color: #ffeaa7; color: #6c5b00; }
        .type-source_sca { background-color: #f8d7da; color: #721c24; }
        .type-vulnerability_analysis { background-color: #d1ecf1; color: #0c5460; }
        .type-sbom_import { background-color: #e2e3f3; color: #383d41; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <div class="logo-container">
                <img src="https://finitestate.io/hs-fs/hubfs/FS-Logo-Final-01.png?width=256&height=50&name=FS-Logo-Final-01.png" 
                     alt="Finite State Logo" 
                     class="company-logo">
            </div>
            <h1>Scan Analysis</h1>
            <div class="subtitle">Operational Insights and Performance Metrics</div>
        </div>
        
        <div class="metadata">
            <strong>Report:</strong> {{ recipe_name }} | 
            <strong>Generated:</strong> {{ generated_at }} | 
            <strong>Date Range:</strong> {{ start_date }} to {{ end_date }}
        </div>
        
        <!-- Summary Cards -->
        {% if table_data and table_data.rows %}
            {% set summary_row = table_data.rows[-1] %}
            <div class="summary-cards">
                <div class="summary-card">
                    <h3>Total Scans</h3>
                    <div class="value">{{ summary_row.total_scans_started }}</div>
                    <div class="unit">scans started</div>
                </div>
                <div class="summary-card">
                    <h3>Projects</h3>
                    <div class="value">{{ summary_row.unique_projects }}</div>
                    <div class="unit">{{ summary_row.new_projects }} new / {{ summary_row.existing_projects }} existing</div>
                </div>
                <div class="summary-card">
                    <h3>Versions</h3>
                    <div class="value">{{ summary_row.unique_versions }}</div>
                    <div class="unit">artifacts processed</div>
                </div>
                <div class="summary-card">
                    <h3>Success Rate</h3>
                    {% set success_rate = ((summary_row.total_scans_started - summary_row.failed_scans) / summary_row.total_scans_started * 100) if summary_row.total_scans_started > 0 else 0 %}
                    <div class="value">{{ "%.1f"|format(success_rate) }}%</div>
                    <div class="unit">{{ summary_row.total_scans_started - summary_row.failed_scans }} succeeded</div>
                </div>
                <div class="summary-card">
                    <h3>Average Duration</h3>
                    <div class="value">{{ "%.0f"|format(summary_row.median_duration_minutes) }}</div>
                    <div class="unit">minutes</div>
                </div>
                <div class="summary-card">
                    <h3>Queue Size</h3>
                    <div class="value">{{ summary_row.recently_queued }}</div>
                    <div class="unit">scans waiting</div>
                </div>
                <div class="summary-card">
                    <h3>Failed Scans</h3>
                    <div class="value">{{ summary_row.failed_scans }}</div>
                    <div class="unit">scans failed</div>
                </div>
            </div>
        {% endif %}
        
        <!-- Charts Section -->
        {% if table_data and table_data.rows %}
            <!-- Scan Throughput Over Time -->
            <div class="chart-container">
                <h2 class="chart-title">📈 Scan Throughput Over Time</h2>
                <p class="chart-description">Daily scan volume showing started vs completed scans</p>
                <div class="chart-wrapper">
                    <canvas id="throughputChart"></canvas>
                </div>
            </div>
            
            <!-- Scan Duration Analysis -->
            <div class="chart-container">
                <h2 class="chart-title">⏱️ Average Scan Duration by Day</h2>
                <p class="chart-description">Average time to complete scans (in minutes)</p>
                <div class="chart-wrapper">
                    <canvas id="durationChart"></canvas>
                </div>
            </div>
            
            <!-- Success Rate -->
            <div class="chart-container">
                <h2 class="chart-title">✅ Daily Success Rate</h2>
                <p class="chart-description">Percentage of successful vs failed scans by day</p>
                <div class="chart-wrapper">
                    <canvas id="successChart"></canvas>
                </div>
            </div>
            
            <!-- Scan Type Distribution -->
            <div class="chart-container">
                <h2 class="chart-title">🔧 Scan Type Distribution</h2>
                <p class="chart-description">Breakdown of scan types (SCA, SAST, CONFIG)</p>
                <div class="chart-wrapper">
                    <canvas id="typeChart"></canvas>
                </div>
            </div>
            
            <!-- Scan Failures Over Time -->
            <div class="chart-container">
                <h2 class="chart-title">❌ Scan Failures Over Time</h2>
                <p class="chart-description">Failure volume by scan type (bars) with overall failure rate (line) - highlights problematic periods</p>
                <div class="chart-wrapper">
                    <canvas id="failureTypeChart"></canvas>
                </div>
            </div>
        {% else %}
            <div class="no-data">
                <p>No scan data available for the selected time period.</p>
            </div>
        {% endif %}
        
        <!-- Data Table -->
        {% if table_data and table_data.rows %}
        <div class="table-container">
            <h2>Daily Scan Metrics</h2>
            <table>
                <thead>
                    <tr>
                        <th rowspan="2">Date</th>
                        <th rowspan="2">Started</th>
                        <th rowspan="2">Projects</th>
                        <th rowspan="2">New</th>
                        <th rowspan="2">Existing</th>
                        <th rowspan="2">Versions</th>
                        <th rowspan="2">Completed</th>
                        <th rowspan="2">Failed</th>
                        <th rowspan="2">In Progress</th>
                        <th rowspan="2">Success Rate</th>
                        <th rowspan="2">Avg Duration (min)</th>
                        <th colspan="6" style="text-align: center;">Scan Counts by Type</th>
                    </tr>
                    <tr>
                        <th>SCA</th>
                        <th>SAST</th>
                        <th>CONFIG</th>
                        <th>SOURCE SCA</th>
                        <th>REACHABILITY</th>
                        <th>IMPORT</th>
                    </tr>
                </thead>
                <tbody>
                    {% for row in table_data.rows %}
                    <tr>
                        <td>{{ row.date }}</td>
                        <td>{{ row.total_scans_started }}</td>
                        <td>{{ row.unique_projects }}</td>
                        <td>{{ row.new_projects }}</td>
                        <td>{{ row.existing_projects }}</td>
                        <td>{{ row.unique_versions }}</td>
                        <td>{{ row.total_completed_scans }}</td>
                        <td>{{ row.failed_scans }}</td>
                        <td>{{ row.still_active_scans }}</td>
                        <td class="success-rate {% if row.success_rate >= 90 %}high{% elif row.success_rate >= 70 %}medium{% else %}low{% endif %}">
                            {{ "%.1f"|format(row.success_rate) }}%
                        </td>
                        <td>{{ "%.0f"|format(row.avg_duration_minutes) if row.avg_duration_minutes > 0 else "-" }}</td>
                        <td>{{ row.sca_scans }}</td>
                        <td>{{ row.sast_scans }}</td>
                        <td>{{ row.config_scans }}</td>
                        <td>{{ row.source_sca_scans }}</td>
                        <td>{{ row.vulnerability_analysis_scans }}</td>
                        <td>{{ row.sbom_import_scans }}</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
        {% endif %}
        
        <!-- Raw Scan Data Table -->
        {% if raw_data %}
        <div class="table-container">
            <h2>📋 Individual Scan Details</h2>
            <p style="color: #6c757d; margin-bottom: 15px;">
                Complete list of all scans for detailed analysis and custom reporting.
                This data is also available in the CSV and XLSX downloads.
            </p>
            <table>
                <thead>
                    <tr>
                        <th>Scan ID</th>
                        <th>Date Started</th>
                        <th>Date Completed</th>
                        <th>Status</th>
                        <th>Type</th>
                        {% if folder_path %}<th>Folder</th>{% endif %}
                        <th>Project</th>
                        <th>Version</th>
                        <th>Duration (min)</th>
                        <th>Error Message</th>
                    </tr>
                </thead>
                <tbody>
                    {% if raw_data.iterrows %}
                        {% for _, row in raw_data.iterrows() %}
                        <tr>
                            <td style="font-family: monospace; font-size: 0.9em;">{{ row.get('id', 'N/A') }}</td>
                            <td>{{ row.get('scan_date', 'N/A') }}</td>
                            <td>{{ row.get('completion_date', 'N/A') if row.get('completion_date') != 'NaT' else '-' }}</td>
                            <td>
                                <span class="status-badge status-{{ row.get('status', 'unknown').lower() }}">
                                    {{ row.get('status', 'N/A') }}
                                </span>
                            </td>
                            <td>
                                <span class="type-badge type-{{ row.get('type', 'unknown').lower() }}">
                                    {{ row.get('type', 'N/A') }}
                                </span>
                            </td>
                            {% if folder_path %}<td>{{ row.get('folder_name', '') }}</td>{% endif %}
                            <td>{{ row.get('project_name', 'N/A') }}</td>
                            <td>{{ row.get('version_name', '-') if row.get('version_name') else '-' }}</td>
                            <td>{{ "%.1f"|format(row.get('duration_minutes', 0)) if row.get('duration_minutes', 0) > 0 else '-' }}</td>
                            <td style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="{{ row.get('errorMessage', '') }}">
                                {{ row.get('errorMessage', '-') if row.get('errorMessage') else '-' }}
                            </td>
                        </tr>
                        {% endfor %}
                    {% else %}
                        {% for row in raw_data %}
                        <tr>
                            <td style="font-family: monospace; font-size: 0.9em;">{{ row.get('id', 'N/A') }}</td>
                            <td>{{ row.get('scan_date', 'N/A') }}</td>
                            <td>{{ row.get('completion_date', 'N/A') if row.get('completion_date') != 'NaT' else '-' }}</td>
                            <td>
                                <span class="status-badge status-{{ row.get('status', 'unknown').lower() }}">
                                    {{ row.get('status', 'N/A') }}
                                </span>
                            </td>
                            <td>
                                <span class="type-badge type-{{ row.get('type', 'unknown').lower() }}">
                                    {{ row.get('type', 'N/A') }}
                                </span>
                            </td>
                            {% if folder_path %}<td>{{ row.get('folder_name', '') }}</td>{% endif %}
                            <td>{{ row.get('project_name', 'N/A') }}</td>
                            <td>{{ row.get('version_name', '-') if row.get('version_name') else '-' }}</td>
                            <td>{{ "%.1f"|format(row.get('duration_minutes', 0)) if row.get('duration_minutes', 0) > 0 else '-' }}</td>
                            <td style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="{{ row.get('errorMessage', '') }}">
                                {{ row.get('errorMessage', '-') if row.get('errorMessage') else '-' }}
                            </td>
                        </tr>
                        {% endfor %}
                    {% endif %}
                </tbody>
            </table>
        </div>
        {% endif %}
        
        <div class="footer">
            <p>Generated by <span class="finite-state-logo">Finite State</span> | {{ generated_at }}</p>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            {% if table_data and table_data.rows %}
                // Prepare data (exclude summary row) - now using named access
                const data = {{ table_data.rows[:-1] | tojson }};
                const labels = data.map(row => row.period);
                
                // Moving average helper function
                function movingAverage(arr, window) {
                    return arr.map((_, i) => {
                        const start = Math.max(0, i - window + 1);
                        const slice = arr.slice(start, i + 1);
                        return slice.reduce((a, b) => a + b, 0) / slice.length;
                    });
                }
                
                // Adaptive window: 7-day if < 30 data points, 14-day otherwise
                const windowSize = data.length < 30 ? 7 : 14;
                
                // Throughput Chart with Moving Averages
                const throughputCtx = document.getElementById('throughputChart').getContext('2d');
                const scansStartedData = data.map(row => row.total_scans_started);
                const scansCompletedData = data.map(row => row.total_completed_scans);
                
                new Chart(throughputCtx, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: 'Scans Started',
                            data: scansStartedData,
                            borderColor: 'rgb(54, 162, 235)',
                            backgroundColor: 'rgba(54, 162, 235, 0.1)',
                            fill: false
                        }, {
                            label: 'Scans Completed', 
                            data: scansCompletedData,
                            borderColor: 'rgb(75, 192, 192)',
                            backgroundColor: 'rgba(75, 192, 192, 0.1)',
                            fill: false
                        }, {
                            label: `Started (${windowSize}-day MA)`,
                            data: movingAverage(scansStartedData, windowSize),
                            borderColor: 'rgba(54, 162, 235, 0.5)',
                            borderDash: [5, 5],
                            fill: false,
                            pointRadius: 0
                        }, {
                            label: `Completed (${windowSize}-day MA)`,
                            data: movingAverage(scansCompletedData, windowSize),
                            borderColor: 'rgba(75, 192, 192, 0.5)',
                            borderDash: [5, 5],
                            fill: false,
                            pointRadius: 0
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true,
                                title: {
                                    display: true,
                                    text: 'Number of Scans'
                                }
                            }
                        }
                    }
                });
                
                // Duration Chart
                const durationCtx = document.getElementById('durationChart').getContext('2d');
                new Chart(durationCtx, {
                    type: 'bar',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: 'Average Duration (minutes)',
                            data: data.map(row => row.avg_duration_minutes),
                            backgroundColor: 'rgba(255, 159, 64, 0.8)',
                            borderColor: 'rgb(255, 159, 64)',
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true,
                                title: {
                                    display: true,
                                    text: 'Duration (minutes)'
                                }
                            }
                        }
                    }
                });
                
                // Success Rate Chart
                const successCtx = document.getElementById('successChart').getContext('2d');
                new Chart(successCtx, {
                    type: 'bar',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: 'Success Rate (%)',
                            data: data.map(row => row.success_rate),
                            backgroundColor: data.map(row => {
                                if (row.success_rate >= 90) return 'rgba(40, 167, 69, 0.8)';
                                if (row.success_rate >= 70) return 'rgba(255, 193, 7, 0.8)';
                                return 'rgba(220, 53, 69, 0.8)';
                            }),
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true,
                                max: 100,
                                title: {
                                    display: true,
                                    text: 'Success Rate (%)'
                                }
                            }
                        }
                    }
                });
                
                // Scan Type Distribution (using overall totals)
                const summaryRow = {{ table_data.rows[-1] | tojson }};
                const typeCtx = document.getElementById('typeChart').getContext('2d');
                
                // Filter out scan types with 0 scans to make chart cleaner
                const allScanTypes = [
                    { label: 'SCA', count: summaryRow.sca_scans, color: 'rgba(255, 99, 132, 0.8)' },
                    { label: 'SAST', count: summaryRow.sast_scans, color: 'rgba(54, 162, 235, 0.8)' },
                    { label: 'CONFIG', count: summaryRow.config_scans, color: 'rgba(255, 205, 86, 0.8)' },
                    { label: 'SOURCE_SCA', count: summaryRow.source_sca_scans, color: 'rgba(75, 192, 192, 0.8)' },
                    { label: 'VULNERABILITY_ANALYSIS', count: summaryRow.vulnerability_analysis_scans, color: 'rgba(153, 102, 255, 0.8)' },
                    { label: 'SBOM_IMPORT', count: summaryRow.sbom_import_scans, color: 'rgba(255, 159, 64, 0.8)' }
                ];
                
                // Only include types with at least 1 scan
                const activeScanTypes = allScanTypes.filter(type => type.count > 0);
                
                new Chart(typeCtx, {
                    type: 'pie',
                    data: {
                        labels: activeScanTypes.map(type => type.label),
                        datasets: [{
                            data: activeScanTypes.map(type => type.count),
                            backgroundColor: activeScanTypes.map(type => type.color),
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {
                            legend: {
                                position: 'bottom'
                            }
                        }
                    }
                });
                
                // Scan Failures Over Time - Dual Axis Chart
                const failureCtx = document.getElementById('failureTypeChart').getContext('2d');
                
                // Stacked bar datasets for failure counts by type + line for failure rate
                const failureDatasets = [
                    {
                        label: 'SCA Failures',
                        data: data.map(row => row.sca_failures || 0),
                        backgroundColor: 'rgba(255, 99, 132, 0.8)',
                        stack: 'failures',
                        yAxisID: 'y'
                    },
                    {
                        label: 'SAST Failures',
                        data: data.map(row => row.sast_failures || 0),
                        backgroundColor: 'rgba(54, 162, 235, 0.8)',
                        stack: 'failures',
                        yAxisID: 'y'
                    },
                    {
                        label: 'CONFIG Failures',
                        data: data.map(row => row.config_failures || 0),
                        backgroundColor: 'rgba(255, 205, 86, 0.8)',
                        stack: 'failures',
                        yAxisID: 'y'
                    },
                    {
                        label: 'Reachability Failures',
                        data: data.map(row => row.vulnerability_analysis_failures || 0),
                        backgroundColor: 'rgba(153, 102, 255, 0.8)',
                        stack: 'failures',
                        yAxisID: 'y'
                    },
                    // Failure rate line (right axis)
                    {
                        label: 'Failure Rate %',
                        data: data.map(row => row.failure_rate || 0),
                        type: 'line',
                        borderColor: 'rgb(220, 53, 69)',
                        backgroundColor: 'transparent',
                        borderWidth: 2,
                        yAxisID: 'y1',
                        pointRadius: 3
                    }
                ];

                new Chart(failureCtx, {
                    type: 'bar',
                    data: { labels: labels, datasets: failureDatasets },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                type: 'linear',
                                position: 'left',
                                beginAtZero: true,
                                stacked: true,
                                title: { display: true, text: 'Failed Scans' }
                            },
                            y1: {
                                type: 'linear',
                                position: 'right',
                                beginAtZero: true,
                                max: 100,
                                grid: { drawOnChartArea: false },
                                title: { display: true, text: 'Failure Rate (%)' }
                            },
                            x: { stacked: true }
                        },
                        plugins: {
                            legend: {
                                position: 'bottom'
                            }
                        }
                    }
                });
            {% endif %}
        });
    </script>
</body>
</html> 