import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:siro_driver/constant/box_name.dart';
import 'package:siro_driver/constant/links.dart';
import 'package:siro_driver/controller/functions/crud.dart';
import '../../main.dart';

// ════════════════════════════════════════════
//  نماذج البيانات
// ════════════════════════════════════════════

class DriverLevel {
  final String id;
  final String nameEn;
  final String nameAr;
  final String emoji;
  final Color color;
  final Color gradientEnd;
  final int minPoints;
  final int maxPoints;
  final double commissionDiscount; // نسبة الخصم على العمولة
  final List<String> perks;

  const DriverLevel({
    required this.id,
    required this.nameEn,
    required this.nameAr,
    required this.emoji,
    required this.color,
    required this.gradientEnd,
    required this.minPoints,
    required this.maxPoints,
    required this.commissionDiscount,
    required this.perks,
  });
}

class Achievement {
  final String id;
  final String titleEn;
  final String titleAr;
  final String descriptionEn;
  final String descriptionAr;
  final IconData icon;
  final Color color;
  final int target;
  final String type; // 'trips', 'rating', 'earnings', 'streak', 'referral'
  bool isUnlocked;
  int currentProgress;
  final DateTime? unlockedAt;

  Achievement({
    required this.id,
    required this.titleEn,
    required this.titleAr,
    required this.descriptionEn,
    required this.descriptionAr,
    required this.icon,
    required this.color,
    required this.target,
    required this.type,
    this.isUnlocked = false,
    this.currentProgress = 0,
    this.unlockedAt,
  });

  double get progress => (currentProgress / target).clamp(0.0, 1.0);
}

// ════════════════════════════════════════════
//  المستويات الثابتة
// ════════════════════════════════════════════

class DriverLevels {
  static const List<DriverLevel> all = [
    DriverLevel(
      id: 'bronze',
      nameEn: 'Bronze',
      nameAr: 'برونزي',
      emoji: '🥉',
      color: Color(0xFFCD7F32),
      gradientEnd: Color(0xFFE8A854),
      minPoints: 0,
      maxPoints: 999,
      commissionDiscount: 0,
      perks: ['Basic features', 'Standard support'],
    ),
    DriverLevel(
      id: 'silver',
      nameEn: 'Silver',
      nameAr: 'فضي',
      emoji: '🥈',
      color: Color(0xFF9CA3AF),
      gradientEnd: Color(0xFFC0C7D1),
      minPoints: 1000,
      maxPoints: 4999,
      commissionDiscount: 1,
      perks: ['Priority medium', 'Silver badge', '-1% commission'],
    ),
    DriverLevel(
      id: 'gold',
      nameEn: 'Gold',
      nameAr: 'ذهبي',
      emoji: '🥇',
      color: Color(0xFFFFD700),
      gradientEnd: Color(0xFFFFA500),
      minPoints: 5000,
      maxPoints: 14999,
      commissionDiscount: 2,
      perks: ['High priority', 'Gold badge', '-2% commission'],
    ),
    DriverLevel(
      id: 'diamond',
      nameEn: 'Diamond',
      nameAr: 'ألماسي',
      emoji: '💎',
      color: Color(0xFF00BCD4),
      gradientEnd: Color(0xFF3F51B5),
      minPoints: 15000,
      maxPoints: 999999,
      commissionDiscount: 5,
      perks: ['VIP first', 'Diamond badge', '-5% commission', 'Priority support'],
    ),
  ];

  static DriverLevel getLevel(int points) {
    for (int i = all.length - 1; i >= 0; i--) {
      if (points >= all[i].minPoints) return all[i];
    }
    return all.first;
  }

  static DriverLevel? getNextLevel(int points) {
    final current = getLevel(points);
    final idx = all.indexOf(current);
    if (idx < all.length - 1) return all[idx + 1];
    return null;
  }

  static double getProgressToNext(int points) {
    final current = getLevel(points);
    final next = getNextLevel(points);
    if (next == null) return 1.0;
    return ((points - current.minPoints) / (next.minPoints - current.minPoints))
        .clamp(0.0, 1.0);
  }
}

// ════════════════════════════════════════════
//  الـ Controller
// ════════════════════════════════════════════

class GamificationController extends GetxController {
  bool isLoading = false;
  int totalTrips = 0;
  int totalPoints = 0;
  double averageRating = 5.0;
  int totalReferrals = 0;
  int consecutiveDays = 0; // أيام متتالية
  double totalEarnings = 0;

  // === Driving Behavior ===
  double behaviorScore = 100.0;
  int hardBrakes = 0;
  double maxSpeed = 0.0;

  late DriverLevel currentLevel;
  DriverLevel? nextLevel;
  double progressToNext = 0;
  List<Achievement> achievements = [];

  // === Daily Goal ===
  double dailyGoal = 0;
  double dailyEarnings = 0;
  double get dailyGoalProgress =>
      dailyGoal > 0 ? (dailyEarnings / dailyGoal).clamp(0.0, 1.0) : 0.0;
  bool get isDailyGoalMet => dailyGoalProgress >= 1.0;

  @override
  void onInit() {
    super.onInit();
    _loadLocalData();
    _initializeAchievements();
    _calculateLevel();
    fetchGamificationData();
  }

  // ═══════ تحميل البيانات المحلية ═══════
  void _loadLocalData() {
    dailyGoal = (box.read('dailyGoal') ?? 0).toDouble();
    totalTrips = box.read('gamification_totalTrips') ?? 0;
    consecutiveDays = box.read('gamification_consecutiveDays') ?? 0;
    averageRating = (box.read('gamification_averageRating') ?? 5.0).toDouble();
    totalPoints = box.read('gamification_totalPoints') ?? 0;
    totalReferrals = box.read('gamification_totalReferrals') ?? 0;
    dailyEarnings = (box.read('gamification_dailyEarnings') ?? 0.0).toDouble();
    behaviorScore = (box.read('gamification_behaviorScore') ?? 100.0).toDouble();
    hardBrakes = box.read('gamification_hardBrakes') ?? 0;
    maxSpeed = (box.read('gamification_maxSpeed') ?? 0.0).toDouble();
  }

  // ═══════ حفظ البيانات المحلية (التخزين المؤقت) ═══════
  void _saveLocalData() {
    box.write('gamification_totalTrips', totalTrips);
    box.write('gamification_consecutiveDays', consecutiveDays);
    box.write('gamification_averageRating', averageRating);
    box.write('gamification_totalPoints', totalPoints);
    box.write('gamification_totalReferrals', totalReferrals);
    box.write('gamification_dailyEarnings', dailyEarnings);
    box.write('gamification_behaviorScore', behaviorScore);
    box.write('gamification_hardBrakes', hardBrakes);
    box.write('gamification_maxSpeed', maxSpeed);
    box.write('gamification_last_fetch', DateTime.now().toIso8601String());
  }

  // ═══════ حفظ الهدف اليومي ═══════
  void setDailyGoal(double goal) {
    dailyGoal = goal;
    box.write('dailyGoal', goal);
    update();
  }

  void updateDailyEarnings(double earnings) {
    dailyEarnings = earnings;
    update();
  }

  // ═══════ حساب المستوى ═══════
  void _calculateLevel() {
    currentLevel = DriverLevels.getLevel(totalPoints);
    nextLevel = DriverLevels.getNextLevel(totalPoints);
    progressToNext = DriverLevels.getProgressToNext(totalPoints);
    update();
  }

  // ═══════ تهيئة الإنجازات ═══════
  void _initializeAchievements() {
    achievements = [
      Achievement(
        id: 'first_trip',
        titleEn: 'First Trip',
        titleAr: 'أول رحلة',
        descriptionEn: 'Complete your first trip',
        descriptionAr: 'أكمل أول رحلة لك',
        icon: Icons.flag_rounded,
        color: const Color(0xFF4CAF50),
        target: 1,
        type: 'trips',
      ),
      Achievement(
        id: 'trip_50',
        titleEn: 'Road Warrior',
        titleAr: 'محارب الطريق',
        descriptionEn: 'Complete 50 trips',
        descriptionAr: 'أكمل 50 رحلة',
        icon: Icons.local_taxi_rounded,
        color: const Color(0xFF2196F3),
        target: 50,
        type: 'trips',
      ),
      Achievement(
        id: 'trip_100',
        titleEn: 'Century Rider',
        titleAr: 'سائق المئة',
        descriptionEn: 'Complete 100 trips',
        descriptionAr: 'أكمل 100 رحلة',
        icon: Icons.emoji_events_rounded,
        color: const Color(0xFFFF9800),
        target: 100,
        type: 'trips',
      ),
      Achievement(
        id: 'trip_500',
        titleEn: 'Road Legend',
        titleAr: 'أسطورة الطريق',
        descriptionEn: 'Complete 500 trips',
        descriptionAr: 'أكمل 500 رحلة',
        icon: Icons.stars_rounded,
        color: const Color(0xFFE91E63),
        target: 500,
        type: 'trips',
      ),
      Achievement(
        id: 'five_star',
        titleEn: 'Five Star Driver',
        titleAr: 'سائق 5 نجوم',
        descriptionEn: 'Maintain 5.0 rating',
        descriptionAr: 'حافظ على تقييم 5.0',
        icon: Icons.star_rounded,
        color: const Color(0xFFFFD700),
        target: 5,
        type: 'rating',
      ),
      Achievement(
        id: 'streak_7',
        titleEn: 'Weekly Streak',
        titleAr: 'سلسلة أسبوعية',
        descriptionEn: 'Work 7 consecutive days',
        descriptionAr: 'اعمل 7 أيام متتالية',
        icon: Icons.whatshot_rounded,
        color: const Color(0xFFFF5722),
        target: 7,
        type: 'streak',
      ),
      Achievement(
        id: 'streak_30',
        titleEn: 'Monthly Streak',
        titleAr: 'سلسلة شهرية',
        descriptionEn: 'Work 30 consecutive days',
        descriptionAr: 'اعمل 30 يوم متتالي',
        icon: Icons.local_fire_department_rounded,
        color: const Color(0xFFD32F2F),
        target: 30,
        type: 'streak',
      ),
      Achievement(
        id: 'referral_5',
        titleEn: 'Social Butterfly',
        titleAr: 'الفراشة الاجتماعية',
        descriptionEn: 'Refer 5 drivers',
        descriptionAr: 'ادعُ 5 سائقين',
        icon: Icons.people_rounded,
        color: const Color(0xFF9C27B0),
        target: 5,
        type: 'referral',
      ),
    ];
  }

  // ═══════ تحديث تقدم الإنجازات ═══════
  void _updateAchievementProgress() {
    for (var ach in achievements) {
      switch (ach.type) {
        case 'trips':
          ach.currentProgress = totalTrips;
          break;
        case 'rating':
          ach.currentProgress = averageRating >= 5 ? 5 : averageRating.floor();
          break;
        case 'streak':
          ach.currentProgress = consecutiveDays;
          break;
        case 'referral':
          ach.currentProgress = totalReferrals;
          break;
      }
      ach.isUnlocked = ach.currentProgress >= ach.target;
    }
    update();
  }

  // ═══════ جلب البيانات من السيرفر ═══════
  Future<void> fetchGamificationData({bool force = false}) async {
    // التحقق من التخزين المؤقت (6 ساعات)
    String? lastFetchStr = box.read('gamification_last_fetch');
    if (!force && lastFetchStr != null) {
      try {
        DateTime lastFetch = DateTime.parse(lastFetchStr);
        if (DateTime.now().difference(lastFetch).inHours < 6) {
          debugPrint('ℹ️ [Gamification] Loading cached data (last fetch: $lastFetchStr)');
          _loadLocalData();
          _calculateLevel();
          _updateAchievementProgress();
          return;
        }
      } catch (e) {
        debugPrint('⚠️ [Gamification] Failed to parse last fetch time: $e');
      }
    }

    isLoading = true;
    update();

    try {
      var res = await CRUD().get(
        link: AppLink.getGamificationDashboard,
        payload: {'driver_id': box.read(BoxName.driverID).toString()},
      );

      if (res != null && res != 'failure') {
        var data = jsonDecode(res);
        if (data['status'] == 'success' && data['message'] != null) {
          var details = data['message'];
          totalTrips = int.tryParse(details['totalTrips']?.toString() ?? '0') ?? 0;
          averageRating = double.tryParse(details['averageRating']?.toString() ?? '5.0') ?? 5.0;
          totalReferrals = int.tryParse(details['totalReferrals']?.toString() ?? '0') ?? 0;
          dailyEarnings = double.tryParse(details['todayEarnings']?.toString() ?? '0.0') ?? 0.0;
          behaviorScore = double.tryParse(details['behaviorScore']?.toString() ?? '100.0') ?? 100.0;
          hardBrakes = int.tryParse(details['hardBrakes']?.toString() ?? '0') ?? 0;
          maxSpeed = double.tryParse(details['maxSpeed']?.toString() ?? '0.0') ?? 0.0;
          totalPoints = int.tryParse(details['totalPoints']?.toString() ?? '0') ?? 0;
        }
      }

      // 7. حساب الأيام المتتالية (محلياً)
      _calculateConsecutiveDays();
    } catch (e) {
      debugPrint('❌ [Gamification] Error fetching data: $e');
    }

    _calculateLevel();
    _updateAchievementProgress();
    _saveLocalData();
    isLoading = false;
    update();
  }

  void _calculateConsecutiveDays() {
    String? lastActiveDate = box.read('lastActiveDate');
    String today =
        DateTime.now().toIso8601String().split('T')[0]; // 2026-05-08

    if (lastActiveDate == null) {
      consecutiveDays = 1;
    } else if (lastActiveDate == today) {
      // نفس اليوم — لا تغيير
    } else {
      DateTime last = DateTime.parse(lastActiveDate);
      DateTime now = DateTime.parse(today);
      if (now.difference(last).inDays == 1) {
        consecutiveDays++;
      } else {
        consecutiveDays = 1;
      }
    }

    box.write('lastActiveDate', today);
    box.write('gamification_consecutiveDays', consecutiveDays);
  }

  // ═══════ إحصائيات سريعة ═══════
  int get unlockedCount => achievements.where((a) => a.isUnlocked).length;
  int get totalAchievements => achievements.length;
}
