import '../models/sake_item.dart';
import '../models/sakenowa/sakenowa_models.dart';
import 'sakenowa_service.dart';

/// さけのわAPIを使用した外部レコメンデーションサービス
/// 
/// ユーザーがまだ飲んだことがない日本酒を、
/// 五味チャートの好みに基づいておすすめする
class SakenowaRecommendationService {
  final SakenowaService _sakenowaService;

  SakenowaRecommendationService(this._sakenowaService);

  /// ユーザーの好みプロファイルを計算
  UserFlavorProfile calculateUserProfile(List<SakeItem> items) {
    if (items.isEmpty) {
      return UserFlavorProfile.neutral();
    }

    double totalAroma = 0;
    double totalSweetness = 0;
    double totalAcidity = 0;
    double totalBitterness = 0;
    double totalBody = 0;
    int count = 0;

    for (final item in items) {
      final stats = item.hiddenSpecs.tasteStats;
      if (stats.isNotEmpty) {
        totalAroma += (stats['aroma'] ?? 3).toDouble();
        totalSweetness += (stats['sweetness'] ?? 3).toDouble();
        totalAcidity += (stats['acidity'] ?? 3).toDouble();
        totalBitterness += (stats['bitterness'] ?? 3).toDouble();
        totalBody += (stats['body'] ?? 3).toDouble();
        count++;
      }
    }

    if (count == 0) {
      return UserFlavorProfile.neutral();
    }

    return UserFlavorProfile(
      aroma: totalAroma / count,
      sweetness: totalSweetness / count,
      acidity: totalAcidity / count,
      bitterness: totalBitterness / count,
      body: totalBody / count,
    );
  }

  /// さけのわTOP100から類似銘柄を取得
  Future<List<SakenowaRecommendation>> getRecommendations({
    required UserFlavorProfile userProfile,
    required List<SakeItem> existingItems,
    int limit = 10,
  }) async {
    try {
      // ランキングとフレーバーチャートを取得
      final rankings = await _sakenowaService.getRankings();
      final flavorCharts = await _sakenowaService.getFlavorCharts();
      final brands = await _sakenowaService.getBrands();
      final breweries = await _sakenowaService.getBreweries();
      final areas = await _sakenowaService.getAreas();

      // 既存の銘柄名をセットに変換（重複チェック用）
      final existingNames = existingItems
          .map((i) => i.displayData.displayName.toLowerCase())
          .toSet();

      final recommendations = <SakenowaRecommendation>[];

      for (final ranking in rankings.take(100)) {
        // ブランド情報を取得
        final brand = brands.cast<SakenowaBrand?>().firstWhere(
          (b) => b?.id == ranking.brandId,
          orElse: () => null,
        );
        if (brand == null) continue;

        // 既に飲んだ銘柄は除外
        if (existingNames.contains(brand.name.toLowerCase())) continue;

        // フレーバーチャートを取得
        final chart = flavorCharts.cast<SakenowaFlavorChart?>().firstWhere(
          (c) => c?.brandId == ranking.brandId,
          orElse: () => null,
        );

        // 蔵元情報
        final brewery = breweries.cast<SakenowaBrewery?>().firstWhere(
          (b) => b?.id == brand.breweryId,
          orElse: () => null,
        );

        // 地域情報
        final area = areas.cast<SakenowaArea?>().firstWhere(
          (a) => a?.id == brewery?.areaId,
          orElse: () => null,
        );

        // マッチ度を計算
        final matchScore = _calculateMatchScore(userProfile, chart);

        recommendations.add(SakenowaRecommendation(
          brand: brand,
          brewery: brewery,
          area: area,
          flavorChart: chart,
          rank: ranking.rank,
          matchScore: matchScore,
        ));
      }

      // マッチ度でソートして上位を返す
      recommendations.sort((a, b) => b.matchScore.compareTo(a.matchScore));
      return recommendations.take(limit).toList();
    } catch (e) {
      // エラー時は空リストを返す
      return [];
    }
  }

  /// ユーザー好みとさけのわフレーバーのマッチ度を計算
  double _calculateMatchScore(
    UserFlavorProfile user,
    SakenowaFlavorChart? chart,
  ) {
    if (chart == null) return 0.5; // デフォルト中程度

    // 六軸を五味にマッピング
    // 華やか・芳醇 → 香り
    // 芳醇 → 甘み
    // 軽快 → 酸味/キレ
    // 重厚 → コク

    // 各軸は0.0〜1.0の値
    final f1 = chart.f1; // 華やか
    final f2 = chart.f2; // 芳醇
    // final f3 = chart.f3; // 重厚
    // final f4 = chart.f4; // 穏やか
    // final f5 = chart.f5; // ドライ
    final f6 = chart.f6; // 軽快

    // ユーザー好みを0.0〜1.0に正規化（1〜5を0〜1に）
    double normalize(double value) => (value - 1) / 4;

    final userAroma = normalize(user.aroma);
    final userSweetness = normalize(user.sweetness);
    final userAcidity = normalize(user.acidity);

    // 各要素の差分を計算
    double diff = 0;
    diff += (userAroma - (f1 + f2) / 2).abs(); // 香り ↔ 華やか・芳醇
    diff += (userSweetness - f2).abs();         // 甘み ↔ 芳醇
    diff += (userAcidity - f6).abs();           // 酸味 ↔ 軽快

    // 差分をスコアに変換（差が小さいほど高スコア）
    // 最大差は3.0（各要素1.0ずつ）
    final similarity = 1.0 - (diff / 3.0);
    
    // 0.4〜1.0の範囲にスケール
    return 0.4 + (similarity * 0.6);
  }
}

/// ユーザーの好みプロファイル
class UserFlavorProfile {
  final double aroma;
  final double sweetness;
  final double acidity;
  final double bitterness;
  final double body;

  UserFlavorProfile({
    required this.aroma,
    required this.sweetness,
    required this.acidity,
    required this.bitterness,
    required this.body,
  });

  /// デフォルト（ニュートラル）プロファイル
  factory UserFlavorProfile.neutral() {
    return UserFlavorProfile(
      aroma: 3.0,
      sweetness: 3.0,
      acidity: 3.0,
      bitterness: 3.0,
      body: 3.0,
    );
  }
}

/// さけのわおすすめ結果
class SakenowaRecommendation {
  final SakenowaBrand brand;
  final SakenowaBrewery? brewery;
  final SakenowaArea? area;
  final SakenowaFlavorChart? flavorChart;
  final int rank;
  final double matchScore;

  SakenowaRecommendation({
    required this.brand,
    this.brewery,
    this.area,
    this.flavorChart,
    required this.rank,
    required this.matchScore,
  });

  /// マッチパーセンテージ
  int get matchPercent => (matchScore * 100).round();

  /// 地域名（都道府県）
  String get areaName => area?.name ?? '不明';
  
  /// 蔵元名
  String get breweryName => brewery?.name ?? '不明';

  /// フレーバー特徴（上位2つ）
  List<String> get flavorFeatures {
    if (flavorChart == null) return [];
    
    final labels = {
      'f1': '華やか',
      'f2': '芳醇',
      'f3': '重厚',
      'f4': '穏やか',
      'f5': 'ドライ',
      'f6': '軽快',
    };
    
    final values = {
      'f1': flavorChart!.f1,
      'f2': flavorChart!.f2,
      'f3': flavorChart!.f3,
      'f4': flavorChart!.f4,
      'f5': flavorChart!.f5,
      'f6': flavorChart!.f6,
    };
    
    // 上位2つを取得
    final sorted = values.entries.toList()
      ..sort((a, b) => b.value.compareTo(a.value));
    
    return sorted
        .take(2)
        .where((e) => e.value > 0.3) // 閾値以上のみ
        .map((e) => labels[e.key]!)
        .toList();
  }
}
