import '../models/sake_item.dart';
import 'mbti_types.dart';

/// MBTIタイプと日本酒の相性を計算するサービス
/// 
/// ユーザーの公式MBTIタイプと、日本酒のタグ・特定条件・五味チャートを照合して
/// 相性スコア（0.0〜1.0）と理由を返す
class MBTICompatibilityService {
  
  /// 16タイプ別の五味チャート好み（1-5スケール）を公開
  /// { aroma, sweetness, acidity, bitterness, body }
  static Map<String, Map<String, double>> get flavorPreferences => _flavorPreferences;
  
  /// 16タイプ別の五味チャート好み（1-5スケール）
  /// { aroma, sweetness, acidity, bitterness, body }
  static const Map<String, Map<String, double>> _flavorPreferences = {
    // 分析家グループ（NT型）- 論理的、複雑な味わい好み
    'INTJ': {'aroma': 4.5, 'sweetness': 2.0, 'acidity': 3.5, 'bitterness': 4.0, 'body': 4.0},
    'INTP': {'aroma': 4.0, 'sweetness': 2.5, 'acidity': 4.0, 'bitterness': 3.5, 'body': 3.0},
    'ENTJ': {'aroma': 4.5, 'sweetness': 2.0, 'acidity': 3.0, 'bitterness': 4.5, 'body': 4.5},
    'ENTP': {'aroma': 4.0, 'sweetness': 3.5, 'acidity': 4.5, 'bitterness': 3.0, 'body': 3.5},
    
    // 外交官グループ（NF型）- 感性的、華やかで甘め好み
    'INFJ': {'aroma': 4.5, 'sweetness': 3.5, 'acidity': 3.0, 'bitterness': 2.5, 'body': 4.0},
    'INFP': {'aroma': 5.0, 'sweetness': 4.0, 'acidity': 2.5, 'bitterness': 2.0, 'body': 3.0},
    'ENFJ': {'aroma': 4.5, 'sweetness': 3.5, 'acidity': 3.0, 'bitterness': 2.5, 'body': 3.5},
    'ENFP': {'aroma': 5.0, 'sweetness': 4.5, 'acidity': 3.5, 'bitterness': 2.0, 'body': 3.0},
    
    // 番人グループ（SJ型）- 伝統的、バランス重視
    'ISTJ': {'aroma': 2.5, 'sweetness': 2.5, 'acidity': 3.0, 'bitterness': 4.0, 'body': 4.0},
    'ISFJ': {'aroma': 3.0, 'sweetness': 4.0, 'acidity': 2.5, 'bitterness': 2.5, 'body': 3.5},
    'ESTJ': {'aroma': 2.5, 'sweetness': 2.0, 'acidity': 3.5, 'bitterness': 4.5, 'body': 4.0},
    'ESFJ': {'aroma': 3.5, 'sweetness': 3.5, 'acidity': 3.0, 'bitterness': 3.0, 'body': 3.5},
    
    // 探検家グループ（SP型）- 冒険的、インパクト重視
    'ISTP': {'aroma': 3.0, 'sweetness': 2.0, 'acidity': 3.5, 'bitterness': 4.0, 'body': 5.0},
    'ISFP': {'aroma': 4.5, 'sweetness': 4.0, 'acidity': 3.5, 'bitterness': 2.0, 'body': 3.0},
    'ESTP': {'aroma': 3.0, 'sweetness': 2.0, 'acidity': 4.0, 'bitterness': 4.5, 'body': 5.0},
    'ESFP': {'aroma': 5.0, 'sweetness': 4.5, 'acidity': 4.0, 'bitterness': 2.0, 'body': 2.5},
  };

  /// 16タイプ別の酒種好み（複数条件）
  static const Map<String, List<String>> _sakeTypePreferences = {
    'INTJ': ['大吟醸', '純米大吟醸', '斗瓶'],
    'INTP': ['実験', '低アルコール', '酵母'],
    'ENTJ': ['大吟醸', '純米大吟醸', '金賞', 'プレミアム'],
    'ENTP': ['貴醸酒', '古酒', '熟成'],
    'INFJ': ['古酒', '熟成', '秘蔵'],
    'INFP': ['春', '夏', '秋', '冬', '限定', '花', '桜'],
    'ENFJ': ['純米吟醸', '吟醸'],
    'ENFP': ['限定', 'コラボ', '可愛い'],
    'ISTJ': ['生酛', '山廃', '純米', '本醸造'],
    'ISFJ': ['特別純米', '純米'],
    'ESTJ': ['辛口', '本醸造', '淡麗'],
    'ESFJ': ['純米', '食中酒', '地酒'],
    'ISTP': ['無濾過', '生原酒', '原酒'],
    'ISFP': ['スパークリング', '微発泡', 'にごり'],
    'ESTP': ['原酒', '高アルコール', '超辛口'],
    'ESFP': ['スパークリング', 'にごり', 'ピンク'],
  };

  /// 相性スコアを計算（0.0〜1.0）
  static CompatibilityResult calculateCompatibility(String? mbtiType, SakeItem sake) {
    if (mbtiType == null || mbtiType.isEmpty) {
      return CompatibilityResult.noMbti();
    }

    final typeProfile = MBTIType.types[mbtiType];
    if (typeProfile == null) {
      return CompatibilityResult.noMbti();
    }

    double score = 0.0;
    final reasons = <String>[];
    double maxPossibleScore = 0.0;

    // 1. 五味チャートマッチング（最大40点）
    final flavorPref = _flavorPreferences[mbtiType];
    final tasteStats = sake.hiddenSpecs.tasteStats;
    
    if (flavorPref != null && tasteStats.isNotEmpty) {
      maxPossibleScore += 40;
      double flavorScore = 0;
      int matchedAxes = 0;
      
      for (final axis in ['aroma', 'sweetness', 'acidity', 'bitterness', 'body']) {
        final pref = flavorPref[axis] ?? 3.0;
        final actual = (tasteStats[axis] ?? 3).toDouble();
        final diff = (pref - actual).abs();
        
        // 差が1以下なら高スコア、2以下なら中スコア
        if (diff <= 1.0) {
          flavorScore += 8; // 8点/軸
          matchedAxes++;
        } else if (diff <= 2.0) {
          flavorScore += 4; // 4点/軸
        }
      }
      
      score += flavorScore;
      
      if (matchedAxes >= 3) {
        reasons.add('五味チャートが好みに合致');
      } else if (matchedAxes >= 2) {
        reasons.add('味わいのバランスが良好');
      }
    } else {
      // 五味データがない場合はニュートラル加点
      maxPossibleScore += 40;
      score += 20;
    }
    
    // 2. タグマッチング（最大30点）
    final sakeTags = sake.hiddenSpecs.flavorTags.map((t) => t.toLowerCase()).toList();
    final favoriteTags = typeProfile.favorableTags.map((t) => t.toLowerCase()).toList();
    
    maxPossibleScore += 30;
    int tagMatchCount = 0;
    final matchedTags = <String>[];
    
    for (final tag in sakeTags) {
      for (final fav in favoriteTags) {
        if (tag.contains(fav) || fav.contains(tag)) {
          tagMatchCount++;
          matchedTags.add(fav);
          break;
        }
      }
    }
    
    // 最大3タグまでカウント（各10点）
    score += (tagMatchCount.clamp(0, 3) * 10);
    
    if (matchedTags.isNotEmpty) {
      reasons.add('「${matchedTags.first}」にマッチ');
    }

    // 3. 酒種マッチング（最大20点）
    final sakeType = sake.hiddenSpecs.type?.toLowerCase() ?? '';
    final sakeName = sake.displayData.displayName.toLowerCase();
    final typePref = _sakeTypePreferences[mbtiType] ?? [];
    
    maxPossibleScore += 20;
    bool typeMatched = false;
    
    for (final pref in typePref) {
      if (sakeType.contains(pref.toLowerCase()) || sakeName.contains(pref.toLowerCase())) {
        score += 20;
        typeMatched = true;
        reasons.add('おすすめ酒種にマッチ');
        break;
      }
    }
    
    // 酒種マッチがなくてもニュートラル加点
    if (!typeMatched) {
      score += 10;
    }

    // 4. 評価補正（最大10点）
    maxPossibleScore += 10;
    final rating = sake.displayData.rating ?? 3.0;
    if (rating >= 4.0) {
      score += 10;
      if (reasons.length < 3) reasons.add('高評価銘柄');
    } else if (rating >= 3.0) {
      score += 5;
    }

    // 最終スコア計算（0.0〜1.0に正規化）
    final normalizedScore = maxPossibleScore > 0 
        ? (score / maxPossibleScore).clamp(0.3, 1.0) 
        : 0.5;

    // 理由がない場合のデフォルト
    if (reasons.isEmpty) {
      reasons.add('バランスの良い一本');
    }

    return CompatibilityResult(
      score: normalizedScore,
      mbtiType: mbtiType,
      reasons: reasons,
    );
  }

  /// 相性パーセンテージを取得（表示用）
  static int getCompatibilityPercent(String? mbtiType, SakeItem sake) {
    final result = calculateCompatibility(mbtiType, sake);
    return (result.score * 100).round();
  }
}

/// 相性計算結果
class CompatibilityResult {
  final double score;
  final String? mbtiType;
  final List<String> reasons;
  final bool hasResult;

  CompatibilityResult({
    required this.score,
    required this.mbtiType,
    required this.reasons,
    this.hasResult = true,
  });

  factory CompatibilityResult.noMbti() {
    return CompatibilityResult(
      score: 0.0,
      mbtiType: null,
      reasons: [],
      hasResult: false,
    );
  }

  /// パーセンテージ表示
  int get percent => (score * 100).round();

  /// 星評価（0〜5）
  int get starRating {
    if (score >= 0.9) return 5;
    if (score >= 0.75) return 4;
    if (score >= 0.6) return 3;
    if (score >= 0.45) return 2;
    return 1;
  }

  /// 星評価文字列
  String get starDisplay {
    const filledStar = '★';
    const emptyStar = '☆';
    return filledStar * starRating + emptyStar * (5 - starRating);
  }

  /// 相性レベル
  String get level {
    if (score >= 0.85) return '最高';
    if (score >= 0.70) return '良好';
    if (score >= 0.55) return '普通';
    if (score >= 0.40) return 'まあまあ';
    return 'お試し';
  }

  /// 主な理由（1つのみ）
  String get primaryReason => reasons.isNotEmpty ? reasons.first : '';
}
