import 'package:flutter_test/flutter_test.dart';
import 'package:agenda_tasks/features/tasks/data/models/task_model.dart';
import 'package:agenda_tasks/features/tasks/domain/entities/task_entity.dart';
import 'package:agenda_tasks/features/tasks/domain/enums/priority.dart';

void main() {
  group('TaskModel', () {
    final testDate = DateTime(2026, 2, 3);
    final testCreatedAt = DateTime(2026, 1, 1, 10, 30, 0);
    final testUpdatedAt = DateTime(2026, 1, 15, 14, 45, 0);

    group('fromJson', () {
      test('should parse complete JSON correctly', () {
        final json = {
          'id': 'task-123',
          'title': 'Test Task',
          'description': 'Task description',
          'date': '2026-02-03',
          'time': '14:30',
          'priority': 'high',
          'is_done': true,
          'created_at': '2026-01-01T10:30:00.000',
          'updated_at': '2026-01-15T14:45:00.000',
        };

        final task = TaskModel.fromJson(json);

        expect(task.id, 'task-123');
        expect(task.title, 'Test Task');
        expect(task.description, 'Task description');
        expect(task.date, testDate);
        expect(task.time, '14:30');
        expect(task.priority, Priority.high);
        expect(task.isDone, true);
        expect(task.createdAt, testCreatedAt);
        expect(task.updatedAt, testUpdatedAt);
      });

      test('should parse minimal JSON correctly', () {
        final json = {
          'id': 'task-123',
          'title': 'Minimal Task',
          'date': '2026-02-03',
        };

        final task = TaskModel.fromJson(json);

        expect(task.id, 'task-123');
        expect(task.title, 'Minimal Task');
        expect(task.description, isNull);
        expect(task.date, testDate);
        expect(task.time, isNull);
        expect(task.priority, Priority.medium);
        expect(task.isDone, false);
        expect(task.createdAt, isNull);
        expect(task.updatedAt, isNull);
      });

      test('should default to medium priority when priority is null', () {
        final json = {
          'id': 'task-123',
          'title': 'Test Task',
          'date': '2026-02-03',
          'priority': null,
        };

        final task = TaskModel.fromJson(json);

        expect(task.priority, Priority.medium);
      });

      test('should default to false for is_done when null', () {
        final json = {
          'id': 'task-123',
          'title': 'Test Task',
          'date': '2026-02-03',
          'is_done': null,
        };

        final task = TaskModel.fromJson(json);

        expect(task.isDone, false);
      });

      test('should parse all priority levels', () {
        for (final priority in ['low', 'medium', 'high']) {
          final json = {
            'id': 'task-123',
            'title': 'Test Task',
            'date': '2026-02-03',
            'priority': priority,
          };

          final task = TaskModel.fromJson(json);

          expect(task.priority, Priority.fromString(priority));
        }
      });
    });

    group('toJson', () {
      test('should serialize to JSON correctly', () {
        final task = TaskModel(
          id: 'task-123',
          title: 'Test Task',
          description: 'Task description',
          date: testDate,
          time: '14:30',
          priority: Priority.high,
          isDone: true,
        );

        final json = task.toJson();

        expect(json['id'], 'task-123');
        expect(json['title'], 'Test Task');
        expect(json['description'], 'Task description');
        expect(json['date'], '2026-02-03');
        expect(json['time'], '14:30');
        expect(json['priority'], 'high');
        expect(json['is_done'], true);
      });

      test('should format date with leading zeros', () {
        final task = TaskModel(
          id: 'task-123',
          title: 'Test Task',
          date: DateTime(2026, 1, 5),
        );

        final json = task.toJson();

        expect(json['date'], '2026-01-05');
      });

      test('should include null values for optional fields', () {
        final task = TaskModel(
          id: 'task-123',
          title: 'Test Task',
          date: testDate,
        );

        final json = task.toJson();

        expect(json.containsKey('description'), true);
        expect(json['description'], isNull);
        expect(json.containsKey('time'), true);
        expect(json['time'], isNull);
      });
    });

    group('toCreateJson', () {
      test('should not include id in create JSON', () {
        final task = TaskModel(
          id: 'task-123',
          title: 'Test Task',
          description: 'Description',
          date: testDate,
          time: '10:00',
          priority: Priority.low,
        );

        final json = task.toCreateJson();

        expect(json.containsKey('id'), false);
        expect(json['title'], 'Test Task');
        expect(json['description'], 'Description');
        expect(json['date'], '2026-02-03');
        expect(json['time'], '10:00');
        expect(json['priority'], 'low');
      });

      test('should not include is_done in create JSON', () {
        final task = TaskModel(
          id: 'task-123',
          title: 'Test Task',
          date: testDate,
          isDone: true,
        );

        final json = task.toCreateJson();

        expect(json.containsKey('is_done'), false);
      });
    });

    group('fromEntity', () {
      test('should create TaskModel from TaskEntity', () {
        final entity = TaskEntity(
          id: 'entity-123',
          title: 'Entity Task',
          description: 'Entity description',
          date: testDate,
          time: '09:00',
          priority: Priority.high,
          isDone: true,
          createdAt: testCreatedAt,
          updatedAt: testUpdatedAt,
        );

        final model = TaskModel.fromEntity(entity);

        expect(model.id, entity.id);
        expect(model.title, entity.title);
        expect(model.description, entity.description);
        expect(model.date, entity.date);
        expect(model.time, entity.time);
        expect(model.priority, entity.priority);
        expect(model.isDone, entity.isDone);
        expect(model.createdAt, entity.createdAt);
        expect(model.updatedAt, entity.updatedAt);
      });
    });

    group('round-trip serialization', () {
      test('should maintain data after fromJson -> toJson', () {
        final originalJson = {
          'id': 'task-123',
          'title': 'Test Task',
          'description': 'Description',
          'date': '2026-02-03',
          'time': '14:30',
          'priority': 'high',
          'is_done': true,
        };

        final task = TaskModel.fromJson(originalJson);
        final resultJson = task.toJson();

        expect(resultJson['id'], originalJson['id']);
        expect(resultJson['title'], originalJson['title']);
        expect(resultJson['description'], originalJson['description']);
        expect(resultJson['date'], originalJson['date']);
        expect(resultJson['time'], originalJson['time']);
        expect(resultJson['priority'], originalJson['priority']);
        expect(resultJson['is_done'], originalJson['is_done']);
      });
    });
  });
}
