import 'package:flutter/foundation.dart';

import 'package:asciineverdie/src/core/engine/ad_service.dart';
import 'package:asciineverdie/src/core/engine/iap_service.dart';

/// 복귀 보상 데이터 (Phase 7)
class ReturnReward {
  const ReturnReward({
    required this.hoursAway,
    required this.goldReward,
    required this.bonusGold,
  });

  /// 떠나있던 시간 (시간 단위)
  final int hoursAway;

  /// 기본 골드 보상
  final int goldReward;

  /// 보너스 골드 (광고 시청 시 추가)
  final int bonusGold;

  /// 총 보상 (광고 포함)
  int get totalGold => goldReward + bonusGold;

  /// 보상이 있는지 여부
  bool get hasReward => goldReward > 0;
}

/// 복귀 보상 서비스 (Phase 7)
///
/// 플레이어가 게임에 복귀했을 때 떠나있던 시간에 따라 보상을 제공합니다.
/// - 최소 복귀 시간: 1시간
/// - 최대 복귀 시간: 24시간 (그 이상은 24시간으로 계산)
/// - 기본 보상: 시간당 100골드
/// - 보너스 보상: 광고 시청 시 2배
class ReturnRewardsService {
  ReturnRewardsService._();

  static ReturnRewardsService? _instance;

  /// 싱글톤 인스턴스
  static ReturnRewardsService get instance {
    _instance ??= ReturnRewardsService._();
    return _instance!;
  }

  // ===========================================================================
  // 상수
  // ===========================================================================

  /// 최소 복귀 시간 (시간)
  static const int minHoursAway = 1;

  /// 최대 복귀 시간 (시간) - 이 이상은 동일 보상
  static const int maxHoursAway = 24;

  /// 시간당 골드 보상
  static const int goldPerHour = 100;

  /// 레벨당 골드 보상 배수
  static const double goldPerLevelMultiplier = 0.1;

  // ===========================================================================
  // 보상 계산
  // ===========================================================================

  /// 복귀 보상 계산
  ///
  /// [lastPlayTime] 마지막 플레이 시각 (null이면 보상 없음)
  /// [currentTime] 현재 시각
  /// [playerLevel] 플레이어 레벨 (레벨 보너스 계산용)
  /// Returns: 복귀 보상 데이터 (시간이 부족하면 hasReward = false)
  ReturnReward calculateReward({
    required DateTime? lastPlayTime,
    required DateTime currentTime,
    required int playerLevel,
  }) {
    // 마지막 플레이 시간이 없으면 보상 없음
    if (lastPlayTime == null) {
      debugPrint('[ReturnRewards] No lastPlayTime, no reward');
      return const ReturnReward(hoursAway: 0, goldReward: 0, bonusGold: 0);
    }

    // 경과 시간 계산
    final difference = currentTime.difference(lastPlayTime);
    final hoursAway = difference.inHours;

    // 최소 시간 미만이면 보상 없음
    if (hoursAway < minHoursAway) {
      debugPrint('[ReturnRewards] Only $hoursAway hours, need $minHoursAway');
      return ReturnReward(hoursAway: hoursAway, goldReward: 0, bonusGold: 0);
    }

    // 최대 시간 초과 시 최대로 제한
    final effectiveHours = hoursAway > maxHoursAway ? maxHoursAway : hoursAway;

    // 골드 보상 계산 (레벨 보너스 포함)
    final levelMultiplier = 1.0 + (playerLevel * goldPerLevelMultiplier);
    final baseGold = (effectiveHours * goldPerHour * levelMultiplier).round();

    // 보너스 골드 (광고 시청 시 100% 추가)
    final bonusGold = baseGold;

    debugPrint('[ReturnRewards] $hoursAway hours away, '
        'base=$baseGold, bonus=$bonusGold, level=$playerLevel');

    return ReturnReward(
      hoursAway: hoursAway,
      goldReward: baseGold,
      bonusGold: bonusGold,
    );
  }

  // ===========================================================================
  // 보상 수령
  // ===========================================================================

  /// 기본 보상 수령 (광고 없이)
  ///
  /// [reward] 복귀 보상 데이터
  /// Returns: 수령한 골드 양
  int claimBasicReward(ReturnReward reward) {
    if (!reward.hasReward) return 0;
    debugPrint('[ReturnRewards] Basic reward claimed: ${reward.goldReward}');
    return reward.goldReward;
  }

  /// 보너스 보상 수령 (광고 시청 후)
  ///
  /// 유료 유저: 무료 보너스
  /// 무료 유저: 리워드 광고 시청 후 보너스
  /// [reward] 복귀 보상 데이터
  /// Returns: 수령한 보너스 골드 양 (광고 실패 시 0)
  Future<int> claimBonusReward(ReturnReward reward) async {
    if (!reward.hasReward || reward.bonusGold <= 0) return 0;

    // 유료 유저는 무료 보너스
    if (IAPService.instance.isAdRemovalPurchased) {
      debugPrint('[ReturnRewards] Bonus claimed (paid user): ${reward.bonusGold}');
      return reward.bonusGold;
    }

    // 무료 유저는 리워드 광고 필요
    int bonus = 0;
    final adResult = await AdService.instance.showRewardedAd(
      adType: AdType.rewardRevive, // 복귀 보상용 리워드 광고
      onRewarded: () {
        bonus = reward.bonusGold;
      },
    );

    if (adResult == AdResult.completed || adResult == AdResult.debugSkipped) {
      debugPrint('[ReturnRewards] Bonus claimed (free user with ad): $bonus');
      return bonus;
    }

    debugPrint('[ReturnRewards] Bonus claim failed: $adResult');
    return 0;
  }

  // ===========================================================================
  // 시간 포맷팅
  // ===========================================================================

  /// 복귀 시간을 표시용 문자열로 변환
  String formatHoursAway(int hours) {
    if (hours < 24) {
      return '${hours}h';
    }
    final days = hours ~/ 24;
    final remainingHours = hours % 24;
    if (remainingHours == 0) {
      return '${days}d';
    }
    return '${days}d ${remainingHours}h';
  }
}
