import 'package:http/http.dart' as http;

import '../../../errors/server_exception.dart';
import '../../../http_errors.dart';
import '../../nextcloud_ocs.dart';
import 'get_chat_params.dart';
import 'get_chat_response.dart';

/// Long-poll variant of GetChat (`lookIntoFuture=1`). Bypasses [TalkApi]
/// because that layer treats non-2xx as errors, and we need 304 to be a
/// normal "no new messages" outcome. `setReadMarker=on` lets the server
/// move the read cursor whenever the call returns messages.
class LongPollChat {
  final String chatToken;
  final int lastKnownMessageId;
  final int timeoutSeconds;

  LongPollChat({
    required this.chatToken,
    required this.lastKnownMessageId,
    this.timeoutSeconds = 30,
  });

  /// Returns the response, or `null` on HTTP 304 (server timeout, nothing new).
  Future<GetChatResponse?> run() async {
    final params = GetChatParams(
      lookIntoFuture: GetChatParamsSwitch.on,
      timeout: timeoutSeconds,
      lastKnownMessageId: lastKnownMessageId,
      includeLastKnown: GetChatParamsSwitch.off,
      setReadMarker: GetChatParamsSwitch.on,
      limit: 100,
    );
    final uri = NextcloudOcs.uri(
      'apps/spreed/api/v1/chat/$chatToken',
      queryParameters: params.toJson(),
    );
    final headers = NextcloudOcs.headers();

    final response = (await sendGuarded(
      'LongPollChat $uri',
      () => http
          .get(uri, headers: headers)
          .timeout(Duration(seconds: timeoutSeconds + 15)),
    ))!;

    final status = response.statusCode;
    if (status == 304) return null;
    if (status >= 200 && status < 300) {
      return GetChatResponse.fromJson(NextcloudOcs.decode(response.body))
        ..headers = response.headers;
    }
    throw ServerException(
      statusCode: status,
      technicalDetails: 'LongPollChat $uri: HTTP $status',
    );
  }
}
