import 'dart:convert';
import 'dart:io';

import 'package:mam_core/mam_core.dart';
import 'package:test/test.dart';

String _repoRoot() {
  var dir = Directory.current;
  while (!Directory('${dir.path}/.git').existsSync()) {
    final parent = dir.parent;
    if (parent.path == dir.path) {
      throw StateError(
          'could not locate repo root (.git) from ${Directory.current.path}');
    }
    dir = parent;
  }
  return dir.path;
}

void main() {
  test('SessionsSnapshot.fromJson parses a well-formed sessions_detail payload',
      () {
    final json = jsonDecode('''
    {
      "timestamp": "2026-07-16T11:56:54Z",
      "yaml_path": "/x/.mam/agent-sessions.yaml",
      "tmux_sessions_alive": ["a|default"],
      "tmux_confirmed": true,
      "drifts": [{"class": "B", "name": "a", "msg": "registered: a"}],
      "actions": ["registered: a"],
      "sessions_detail": [
        {
          "name": "a", "server": "default", "status": "running",
          "tmux_alive": true, "cmd": "claude", "role": "creator",
          "resume_state": "yes", "job_id": "-", "job_status": "-",
          "pane_cwd": "/x", "attach_command": "tmux attach -t a",
          "drift_classes": ["B"], "pane_pid": 123, "cmd_full": "claude --foo",
          "start_command": "tmux new-session ...", "last_visible_status": "running"
        }
      ]
    }
    ''') as Map<String, dynamic>;

    final snapshot = SessionsSnapshot.fromJson(json);

    expect(snapshot.tmuxConfirmed, isTrue);
    expect(snapshot.drifts, hasLength(1));
    expect(snapshot.drifts.single.driftClass, 'B');
    expect(snapshot.sessions, hasLength(1));

    final row = snapshot.sessions.single;
    expect(row.name, 'a');
    expect(row.role, 'creator');
    expect(row.resumeState, 'yes');
    expect(row.hasDrift, isTrue);
    expect(row.isTerminal, isFalse);
    expect(row.pane.pid, 123);
    expect(row.pane.cmdFull, 'claude --foo');
    expect(row.attachCommand, 'tmux attach -t a');
  });

  test('SessionsSnapshot.fromJson tolerates missing optional fields', () {
    final json = jsonDecode('{"sessions_detail": [{"name": "bare"}]}')
        as Map<String, dynamic>;
    final snapshot = SessionsSnapshot.fromJson(json);

    expect(snapshot.tmuxConfirmed, isFalse);
    expect(snapshot.sessions.single.name, 'bare');
    expect(snapshot.sessions.single.resumeState, '?');
    expect(snapshot.sessions.single.pane.pid, isNull);
  });

  test(
    'SessionService.fetchSnapshot parses the real status.sh --json output',
    () async {
      final scriptPath =
          '${_repoRoot()}/.agents/skills/multi-agent-mux-status/scripts/status.sh';
      if (!File(scriptPath).existsSync()) {
        markTestSkipped(
            'status.sh not found at $scriptPath in this environment');
        return;
      }

      final service = SessionService(statusScriptPath: scriptPath);
      final snapshot = await service.fetchSnapshot();

      expect(snapshot.yamlPath, isNotEmpty);
      // sessions_detail row count must match tmux_sessions_alive's distinct names.
      final aliveNames = snapshot.tmuxSessionsAlive
          .map((entry) => entry.split('|').first)
          .toSet();
      final detailNames = snapshot.sessions.map((s) => s.name).toSet();
      expect(detailNames, containsAll(aliveNames.intersection(detailNames)));
    },
    timeout: const Timeout(Duration(seconds: 15)),
  );
}
