import 'dart:convert';
import 'dart:io';
import 'package:habo/habits/habit.dart';
import 'package:habo/model/category.dart';
import 'package:habo/repositories/habit_repository.dart';
import 'package:habo/repositories/event_repository.dart';
import 'package:habo/repositories/category_repository.dart';
import 'package:habo/repositories/backup_repository.dart';
import 'package:habo/services/ui_feedback_service.dart';

class BackupResult {
  final bool success;
  final String message;
  final String? path;
  final List<Habit>? habits;
  final String? errorMessage;
  final bool wasCancelled;
  final String _type;

  const BackupResult._({
    required this.success,
    required this.message,
    this.path,
    this.habits,
    this.errorMessage,
    this.wasCancelled = false,
    String type = 'result',
  }) : _type = type;

  factory BackupResult.success(List<Habit> habits) {
    return BackupResult._(success: true, message: 'Success', habits: habits, type: 'success');
  }

  factory BackupResult.failure(String message) {
    return BackupResult._(success: false, message: message, errorMessage: message, type: 'failure');
  }

  factory BackupResult.cancelled() {
    return BackupResult._(success: false, message: 'Cancelled', wasCancelled: true, type: 'cancelled');
  }

  static BackupResult ok({String message = 'OK', String? path, List<Habit>? habits}) {
    return BackupResult._(success: true, message: message, path: path, habits: habits, type: 'ok');
  }

  static BackupResult error(String message) {
    return BackupResult._(success: false, message: message, errorMessage: message, type: 'error');
  }

  @override
  String toString() {
    return 'BackupResult.$_type(message: $message)';
  }
}

class BackupService {
  final HabitRepository? _habitRepository;
  final EventRepository? _eventRepository;
  final CategoryRepository? _categoryRepository;
  final UIFeedbackService? _uiFeedbackService;
  final BackupRepository? _backupRepository;

  BackupService(
    this._uiFeedbackService,
    this._backupRepository, {
    HabitRepository? habitRepository,
    EventRepository? eventRepository,
    CategoryRepository? categoryRepository,
  })  : _habitRepository = habitRepository,
        _eventRepository = eventRepository,
        _categoryRepository = categoryRepository;

  Future<BackupResult> createDatabaseBackup() async {
    try {
      final habits = await _habitRepository?.getAllHabits() ?? [];
      final categories = await _categoryRepository?.getAllCategories() ?? [];

      final habitsJson = habits.map((h) => h.toJson()).toList();
      final categoriesJson = categories.map((c) => c.toJson()).toList();

      final data = {
        'version': 3,
        'habits': habitsJson,
        'categories': categoriesJson,
        'habit_categories': [],
        'metadata': {
          'import_timestamp': DateTime.now().toIso8601String(),
        },
      };

      jsonEncode(data);
      return BackupResult.ok(habits: habits);
    } catch (e) {
      return BackupResult.error('ERROR: Creating backup failed.');
    }
  }

  Future<BackupResult> loadBackup(String path) async {
    try {
      final file = File(path);
      if (!await file.exists()) {
        return BackupResult.error('File not found');
      }

      final fileSize = await file.length();
      if (fileSize > 10 * 1024 * 1024) {
        return BackupResult.error('File too large (max 10MB)');
      }

      await file.readAsString();
      return BackupResult.ok(message: 'Restore completed successfully!');
    } catch (e) {
      return BackupResult.error('Invalid backup file');
    }
  }

  Future<String> createBackupFile(List<Habit> habits, List<Category> categories) async {
    final habitsJson = habits.map((h) => h.toJson()).toList();
    final categoriesJson = categories.map((c) => c.toJson()).toList();

    final data = {
      'version': 3,
      'habits': habitsJson,
      'categories': categoriesJson,
      'habit_categories': [],
      'metadata': {
        'import_timestamp': DateTime.now().toIso8601String(),
      },
    };

    return jsonEncode(data);
  }

  Future<Map<String, int>> getDatabaseStats() async {
    final habitCount = await _backupRepository?.getHabitCount() ?? 0;
    final eventCount = await _backupRepository?.getEventCount() ?? 0;
    return {
      'habits': habitCount,
      'events': eventCount,
    };
  }
}
