import 'package:test/test.dart';
import 'package:oto/oto/agent/agent_config.dart';
import 'package:oto/oto/agent/agent_runner.dart';
import 'package:oto/oto/agent/edge_registration_client.dart';

class FakeEdgeRegistrationClient extends EdgeRegistrationClient {
  final RegistrationResult Function(AgentConfig config) _onRegister;

  FakeEdgeRegistrationClient(this._onRegister);

  @override
  Future<RegistrationResult> register(AgentConfig config) async {
    return _onRegister(config);
  }
}

void main() {
  const validBootstrapYaml = '''
agent:
  id: "agent-123"
  alias: "my-agent"
  enrollment_token: "token-456"
edge:
  url: "127.0.0.1:8080"
runtime:
  install_dir: "/usr/bin"
  workspace_root: "/var/oto"
  log_dir: "/var/log/oto"
''';

  late AgentConfig validConfig;

  setUp(() {
    validConfig = AgentConfig.fromYamlContent(validBootstrapYaml);
  });

  group('EdgeEndpoint', () {
    test('EdgeEndpoint parses host and port from config edge url', () {
      final endpoint1 = EdgeEndpoint.parse('127.0.0.1:8080');
      expect(endpoint1.host, '127.0.0.1');
      expect(endpoint1.port, 8080);

      final endpoint2 = EdgeEndpoint.parse('http://edge-server:9000');
      expect(endpoint2.host, 'edge-server');
      expect(endpoint2.port, 9000);

      final endpoint3 = EdgeEndpoint.parse('https://secure-edge');
      expect(endpoint3.host, 'secure-edge');
      expect(endpoint3.port, 443);

      final endpoint4 = EdgeEndpoint.parse('edge-no-port');
      expect(endpoint4.host, 'edge-no-port');
      expect(endpoint4.port, 80);
    });
  });

  group('AgentRunner', () {
    test('AgentRunner maps config token to register request', () async {
      AgentConfig? capturedConfig;
      final fakeClient = FakeEdgeRegistrationClient((config) {
        capturedConfig = config;
        return RegistrationResult.accepted(
            'node-123', 'alias-123', {'concurrency': 1});
      });

      final runner = DefaultAgentRunner(client: fakeClient, onLog: (msg) {});
      await runner.run(validConfig);

      expect(capturedConfig, isNotNull);
      expect(capturedConfig!.agent.enrollmentToken, 'token-456');
    });

    test('AgentRunner reports rejected registration', () async {
      final fakeClient = FakeEdgeRegistrationClient((config) {
        return RegistrationResult.rejected('Invalid token');
      });

      final runner = DefaultAgentRunner(client: fakeClient, onLog: (msg) {});
      expect(
        () => runner.run(validConfig),
        throwsA(isA<RegistrationException>()
            .having((e) => e.message, 'message', 'Invalid token')),
      );
    });
  });
}
