import 'package:flutter/foundation.dart';
import '../models/sake_item.dart';
import '../models/sakenowa/sakenowa_models.dart';
import '../utils/string_similarity.dart';
import 'sakenowa_service.dart';

/// マッチング結果
class MatchResult {
  final SakenowaBrand? brand;
  final SakenowaBrewery? brewery;
  final SakenowaArea? area;
  final SakenowaFlavorChart? flavorChart;
  final double score; // 0.0-1.0
  final bool isConfident; // スコア >= 0.8

  MatchResult({
    this.brand,
    this.brewery,
    this.area,
    this.flavorChart,
    required this.score,
    required this.isConfident,
  });

  bool get hasMatch => brand != null;
}

/// さけのわ自動マッチングサービス
///
/// ユーザーが登録した日本酒を自動的にさけのわデータベースとマッチング
/// 銘柄名の統一、正確なフレーバーチャート取得に使用
class SakenowaAutoMatchingService {
  final SakenowaService _sakenowaService;

  SakenowaAutoMatchingService(this._sakenowaService);

  /// 日本酒をさけのわデータベースとマッチング
  ///
  /// [sakeItem]: マッチング対象の日本酒
  /// [minScore]: 最小類似度スコア（デフォルト: 0.7）
  /// [autoApply]: マッチング結果を自動で適用（デフォルト: false）
  ///
  /// Returns: マッチング結果（見つからない場合はscoreが0）
  Future<MatchResult> matchSake({
    required SakeItem sakeItem,
    double minScore = 0.7,
    bool autoApply = false,
  }) async {
    try {
      debugPrint('🔍 [SakenowaAutoMatching] 開始: ${sakeItem.displayData.displayName}');

      // さけのわデータ取得
      final brands = await _sakenowaService.getBrands();
      final breweries = await _sakenowaService.getBreweries();
      final areas = await _sakenowaService.getAreas();
      final flavorCharts = await _sakenowaService.getFlavorCharts();

      debugPrint('📊 [SakenowaAutoMatching] データ取得完了: ${brands.length} brands');

      // マップ化
      final breweryMap = {for (var b in breweries) b.id: b};
      final areaMap = {for (var a in areas) a.id: a};
      final chartMap = {for (var c in flavorCharts) c.brandId: c};

      // 最良マッチを探す
      SakenowaBrand? bestBrand;
      double bestScore = 0.0;

      for (final brand in brands) {
        final score = StringSimilarity.sakenowaMatchScore(
          sakeItem.displayData.displayName,
          brand.name,
        );

        if (score > bestScore) {
          bestScore = score;
          bestBrand = brand;
        }
      }

      // 最小スコア未満なら失敗
      if (bestScore < minScore) {
        debugPrint('❌ [SakenowaAutoMatching] スコア不足: $bestScore < $minScore');
        return MatchResult(
          score: bestScore,
          isConfident: false,
        );
      }

      // マッチング成功
      final brewery = bestBrand != null ? breweryMap[bestBrand.breweryId] : null;
      final area = brewery != null ? areaMap[brewery.areaId] : null;
      final chart = bestBrand != null ? chartMap[bestBrand.id] : null;

      debugPrint('✅ [SakenowaAutoMatching] マッチング成功!');
      debugPrint('   銘柄: ${bestBrand?.name} (スコア: $bestScore)');
      debugPrint('   酒蔵: ${brewery?.name}');
      debugPrint('   地域: ${area?.name}');

      final result = MatchResult(
        brand: bestBrand,
        brewery: brewery,
        area: area,
        flavorChart: chart,
        score: bestScore,
        isConfident: bestScore >= 0.8,
      );

      // 自動適用
      if (autoApply && result.hasMatch) {
        await applyMatch(sakeItem, result);
      }

      return result;
    } catch (e, stackTrace) {
      debugPrint('💥 [SakenowaAutoMatching] エラー: $e');
      debugPrint('Stack trace: $stackTrace');
      return MatchResult(
        score: 0.0,
        isConfident: false,
      );
    }
  }

  /// マッチング結果をSakeItemに適用
  ///
  /// DisplayDataのsakenowaフィールドとHiddenSpecsを更新
  Future<void> applyMatch(SakeItem sakeItem, MatchResult result) async {
    if (!result.hasMatch) {
      debugPrint('⚠️  [SakenowaAutoMatching] マッチなし、適用スキップ');
      return;
    }

    try {
      debugPrint('💾 [SakenowaAutoMatching] マッチング結果を適用中...');

      // DisplayData更新（さけのわ統一名称）
      final updatedDisplayData = sakeItem.displayData.copyWith(
        sakenowaName: result.brand?.name,
        sakenowaBrewery: result.brewery?.name,
        sakenowaPrefecture: result.area?.name,
      );

      // HiddenSpecs更新（6軸フレーバーチャート）
      Map<String, double>? flavorChartMap;
      if (result.flavorChart != null) {
        flavorChartMap = {
          'f1': result.flavorChart!.f1,
          'f2': result.flavorChart!.f2,
          'f3': result.flavorChart!.f3,
          'f4': result.flavorChart!.f4,
          'f5': result.flavorChart!.f5,
          'f6': result.flavorChart!.f6,
        };
      }

      final updatedHiddenSpecs = sakeItem.hiddenSpecs.copyWith(
        sakenowaBrandId: result.brand?.id,
        sakenowaFlavorChart: flavorChartMap,
      );

      // SakeItem更新
      sakeItem.displayData = updatedDisplayData;
      sakeItem.hiddenSpecs = updatedHiddenSpecs;

      // Hiveに保存
      await sakeItem.save();

      debugPrint('✅ [SakenowaAutoMatching] 適用完了!');
      debugPrint('   displayName: ${sakeItem.displayData.displayName}');
      debugPrint('   displayBrewery: ${sakeItem.displayData.displayBrewery}');
      debugPrint('   displayPrefecture: ${sakeItem.displayData.displayPrefecture}');
    } catch (e, stackTrace) {
      debugPrint('💥 [SakenowaAutoMatching] 適用エラー: $e');
      debugPrint('Stack trace: $stackTrace');
    }
  }

  /// 複数の日本酒を一括マッチング
  ///
  /// [sakeItems]: マッチング対象のリスト
  /// [minScore]: 最小類似度スコア
  /// [autoApply]: マッチング結果を自動で適用
  ///
  /// Returns: マッチング成功数
  Future<int> matchBatch({
    required List<SakeItem> sakeItems,
    double minScore = 0.7,
    bool autoApply = false,
  }) async {
    debugPrint('🔄 [SakenowaAutoMatching] バッチ処理開始: ${sakeItems.length} 件');

    int successCount = 0;

    for (final sake in sakeItems) {
      final result = await matchSake(
        sakeItem: sake,
        minScore: minScore,
        autoApply: autoApply,
      );

      if (result.hasMatch && result.isConfident) {
        successCount++;
      }
    }

    debugPrint('✅ [SakenowaAutoMatching] バッチ処理完了: $successCount/${sakeItems.length} 成功');

    return successCount;
  }

  /// 既存データのさけのわフィールドをクリア
  ///
  /// デバッグ・テスト用
  Future<void> clearSakenowaData(SakeItem sakeItem) async {
    debugPrint('🧹 [SakenowaAutoMatching] さけのわデータクリア: ${sakeItem.displayData.displayName}');

    final clearedDisplayData = sakeItem.displayData.copyWith(
      sakenowaName: null,
      sakenowaBrewery: null,
      sakenowaPrefecture: null,
    );

    final clearedHiddenSpecs = sakeItem.hiddenSpecs.copyWith(
      sakenowaBrandId: null,
      sakenowaFlavorChart: null,
    );

    sakeItem.displayData = clearedDisplayData;
    sakeItem.hiddenSpecs = clearedHiddenSpecs;

    await sakeItem.save();

    debugPrint('✅ [SakenowaAutoMatching] クリア完了');
  }
}
