// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';

import 'package:analysis_server/src/scheduler/message_scheduler.dart';
import 'package:analysis_server/src/scheduler/scheduler_tracking_listener.dart';
import 'package:analysis_server/src/status/diagnostics.dart';

class MessageSchedulerPage extends DiagnosticPageWithNav {
  new(DiagnosticsSite site)
    : super(
        site,
        'messageScheduler',
        'Message Scheduler',
        description: 'The state of the message scheduler.',
        indentInNav: true,
      );

  @override
  Future<void> generateContent(Map<String, String> params) async {
    var listener = server.messageScheduler.listener;

    buf.writeln('<style> .container { max-width: 1600px; } </style>');

    h3('Status');
    buf.writeln(
      formatOption(
        'Allows overlapping message handlers:',
        MessageScheduler.allowOverlappingHandlers,
      ),
    );
    if (listener is! SchedulerTrackingListener) {
      buf.writeln(formatOption('Tracking listener:', 'none'));
      return;
    }

    var lines = listener.getMessageLog();
    if (lines.isNotEmpty) {
      h3('Messages');
      buf.writeln('<table>');
      buf.writeln(
        '<tr><th>Message</th><th>Pending (on pending)</th><th>Active (on pending)</th><th>Pending (on active)</th><th>Active (on active)</th><th>Queue Time</th><th>Process Time</th><th>Cancelled</th></tr>',
      );
      for (var line in lines) {
        var data = jsonDecode(line) as Map<String, dynamic>;
        buf.writeln('<tr>');
        buf.writeln('<td>${data['message']}</td>');
        _writeCollapsibleList(
          data['pendingMessageCount'] as int,
          (data['pendingMessages'] as List?)?.cast<String>() ?? [],
        );
        _writeCollapsibleList(
          data['activeOnPendingMessageCount'] as int,
          (data['activeOnPendingMessages'] as List?)?.cast<String>() ?? [],
        );
        _writeCollapsibleList(
          data['pendingOnActiveMessageCount'] as int,
          (data['pendingOnActiveMessages'] as List?)?.cast<String>() ?? [],
        );
        _writeCollapsibleList(
          data['activeOnActiveMessageCount'] as int,
          (data['activeOnActiveMessages'] as List?)?.cast<String>() ?? [],
        );
        buf.writeln('<td>${data['queueTime']}</td>');
        buf.writeln('<td>${data['processTime']}</td>');
        buf.writeln('<td>${data['wasCancelled']}</td>');
        buf.writeln('</tr>');
      }
      buf.writeln('</table>');
    }
  }

  void _writeCollapsibleList(int count, List<String> messages) {
    if (count > 0) {
      buf.writeln('<td>');
      buf.writeln('<details>');
      buf.writeln('<summary>$count</summary>');
      for (var message in messages) {
        buf.writeln('$message<br>');
      }
      buf.writeln('</details>');
      buf.writeln('</td>');
    } else {
      buf.writeln('<td>$count</td>');
    }
  }
}
