import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/api/marianumcloud/talk/chat/get_chat_response.dart';
import 'package:marianum_mobile/api/marianumcloud/talk/room/get_room_response.dart';
import 'package:marianum_mobile/view/pages/talk/data/chat_search_controller.dart';

GetChatResponseObject _msg({
  required int id,
  required int timestamp,
  String actorDisplayName = 'Anyone',
  String message = '',
  String systemMessage = '',
  GetRoomResponseObjectMessageType type =
      GetRoomResponseObjectMessageType.comment,
  Map<String, RichObjectString>? params,
}) =>
    GetChatResponseObject(
      id,
      'token',
      GetRoomResponseObjectMessageActorType.user,
      'actor-id',
      actorDisplayName,
      timestamp,
      systemMessage,
      type,
      true,
      '',
      message,
      params,
      null,
      null,
      null,
    );

GetChatResponse _response(List<GetChatResponseObject> messages) =>
    GetChatResponse(messages.toSet());

void main() {
  group('ChatSearchController.findMatches', () {
    test('empty query returns no matches', () {
      final response = _response([
        _msg(id: 1, timestamp: 100, message: 'Hallo'),
      ]);
      expect(ChatSearchController.findMatches(response, ''), isEmpty);
      expect(ChatSearchController.findMatches(response, '   '), isEmpty);
    });

    test('matches message text case-insensitively', () {
      final response = _response([
        _msg(id: 1, timestamp: 100, message: 'Hallo Welt'),
        _msg(id: 2, timestamp: 200, message: 'nichts hier'),
      ]);
      final matches = ChatSearchController.findMatches(response, 'WELT');
      expect(matches.length, 1);
      expect(matches.first.messageId, 1);
    });

    test('matches actor display name', () {
      final response = _response([
        _msg(
          id: 1,
          timestamp: 100,
          actorDisplayName: 'Lisa Maier',
          message: 'irgendwas',
        ),
        _msg(
          id: 2,
          timestamp: 200,
          actorDisplayName: 'Tom Weber',
          message: 'auch was',
        ),
      ]);
      final matches = ChatSearchController.findMatches(response, 'lisa');
      expect(matches.length, 1);
      expect(matches.first.messageId, 1);
    });

    test('system messages match on text but not on actor', () {
      final response = _response([
        _msg(
          id: 1,
          timestamp: 100,
          actorDisplayName: 'Lisa',
          message: 'Lisa ist beigetreten',
          type: GetRoomResponseObjectMessageType.system,
        ),
      ]);
      // Match on text content
      expect(
        ChatSearchController.findMatches(response, 'beigetreten').length,
        1,
      );
      // Actor name alone (not in text) should not match for system messages
      final actorOnlyResponse = _response([
        _msg(
          id: 1,
          timestamp: 100,
          actorDisplayName: 'Lisa',
          message: 'jemand ist beigetreten',
          type: GetRoomResponseObjectMessageType.system,
        ),
      ]);
      expect(
        ChatSearchController.findMatches(actorOnlyResponse, 'lisa'),
        isEmpty,
      );
    });

    test(
      'reaction, poll_voted and message_deleted system messages are filtered out',
      () {
        final response = _response([
          _msg(
            id: 1,
            timestamp: 100,
            message: 'Treffer',
            systemMessage: 'reaction',
            type: GetRoomResponseObjectMessageType.system,
          ),
          _msg(
            id: 2,
            timestamp: 200,
            message: 'Treffer',
            systemMessage: 'poll_voted',
            type: GetRoomResponseObjectMessageType.system,
          ),
          _msg(
            id: 4,
            timestamp: 250,
            message: 'Treffer',
            systemMessage: 'message_deleted',
            type: GetRoomResponseObjectMessageType.system,
          ),
          _msg(id: 3, timestamp: 300, message: 'Treffer'),
        ]);
        final matches = ChatSearchController.findMatches(response, 'Treffer');
        expect(matches.length, 1);
        expect(matches.first.messageId, 3);
      },
    );

    test('rich object parameters are searchable (e.g. file names)', () {
      final response = _response([
        _msg(
          id: 1,
          timestamp: 100,
          message: '{file}',
          params: {
            'file': RichObjectString(
              RichObjectStringObjectType.file,
              '42',
              'hausaufgaben.pdf',
              null,
              null,
            ),
          },
        ),
      ]);
      final matches = ChatSearchController.findMatches(response, 'hausaufgab');
      expect(matches.length, 1);
      expect(matches.first.messageId, 1);
    });

    test('matches are sorted newest first', () {
      final response = _response([
        _msg(id: 1, timestamp: 100, message: 'X'),
        _msg(id: 2, timestamp: 300, message: 'X'),
        _msg(id: 3, timestamp: 200, message: 'X'),
      ]);
      final matches = ChatSearchController.findMatches(response, 'x');
      expect(matches.map((m) => m.messageId).toList(), [2, 3, 1]);
    });
  });
}
