// lib/controllers/team_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:gifunavi/model/team.dart';
import 'package:gifunavi/model/category.dart';
import 'package:gifunavi/model/user.dart';
import 'package:gifunavi/model/entry.dart';

import 'package:gifunavi/services/api_service.dart';
import 'package:gifunavi/widgets/category_change_dialog.dart';
import 'package:gifunavi/routes/app_pages.dart';
import 'package:gifunavi/pages/entry/entry_controller.dart';

import 'package:gifunavi/model/event.dart';


class TeamController extends GetxController {
  final ApiService _apiService;
  //final EntryController _entryController;

  TeamController({
    required ApiService apiService,
    //required EntryController entryController,
  }) : _apiService = apiService;
        //_entryController = entryController;

  final teams = <Team>[].obs;
  final categories = <NewCategory>[].obs;
  final RxList<User> teamMembers = <User>[].obs;
  final teamEntries = <Entry>[].obs;

  final selectedCategory = Rx<NewCategory?>(null);
  final selectedTeam = Rx<Team?>(null);
  final currentUser = Rx<User?>(null);

  final teamName = ''.obs;
  final isLoading = false.obs;
  final error = RxString('');

  @override
  void onInit() async {
    super.onInit();
    try {
      //_apiService = Get.find<ApiService>();

      //if (!Get.isRegistered<EntryController>()) {
      //  Get.put(EntryController());
      //}
      //_entryController = Get.find<EntryController>();

      await loadInitialData();
    } catch (e) {
      error.value = e.toString();
      print('Error in TeamController onInit: $e');
    }
  }

  Future<void> loadInitialData() async {
    try {
      isLoading.value = true;
      await Future.wait([
        fetchCategories(),
        fetchTeams(),
        getCurrentUser(),
      ]);
      if (categories.isNotEmpty && selectedCategory.value == null) {
        selectedCategory.value = categories.first;
      }
    } catch (e) {
      error.value = e.toString();
    } finally {
      isLoading.value = false;
    }
  }



  void setSelectedTeam(Team team) {
    selectedTeam.value = team;
    teamName.value = team.teamName;
    if (categories.isNotEmpty) {
      selectedCategory.value = categories.firstWhere(
            (category) => category.id == team.category.id,
        orElse: () => categories.first,
      );
    } else {
      // カテゴリリストが空の場合、teamのカテゴリをそのまま使用
      selectedCategory.value = team.category;
    }
    fetchTeamMembers(team.id);
  }

  void resetForm() {
    selectedTeam.value = null;
    teamName.value = '';
    if (categories.isNotEmpty) {
      selectedCategory.value = categories.first;
    } else {
      selectedCategory.value = null;
      // カテゴリが空の場合、エラーメッセージをセット
      error.value = 'カテゴリデータが取得できませんでした。';
    }    teamMembers.clear();
  }

  void cleanupForNavigation() {
    selectedTeam.value = null;
    teamName.value = '';
    selectedCategory.value = categories.isNotEmpty ? categories.first : null;
    teamMembers.clear();
    //teamMembersはクリアしない
    // 必要に応じて他のクリーンアップ処理を追加
  }

  Future<void> fetchTeams() async {
    try {
      isLoading.value = true;
      final fetchedTeams = await _apiService.getTeams();
      teams.assignAll(fetchedTeams);
    } catch (e) {
      error.value = 'チームの取得に失敗しました: $e';
      print('Error fetching teams: $e');
    } finally {
      isLoading.value = false;
    }
  }

  bool checkIfUserHasEntryData(){
    if (teams.isEmpty) {
      return false;
    }else {
      return true;
    }
  }

  Future<void> fetchCategories() async {
    try {
      final fetchedCategories = await _apiService.getCategories();
      categories.assignAll(fetchedCategories);
      print("Fetched categories: ${categories.length}");  // デバッグ用

    } catch (e) {
      print('Error fetching categories: $e');
    }
  }

  Future<void> getCurrentUser() async {
    try {
      final user = await _apiService.getCurrentUser();
      currentUser.value = user;
    } catch (e) {
      print('Error getting current user: $e');
    }
  }

  Future<Team> createTeam(String teamName, int categoryId) async {
    final newTeam = await _apiService.createTeam(teamName, categoryId);

    // 自分自身をメンバーとして自動登録
    await _apiService.createTeamMember(
      newTeam.id,
      currentUser.value?.email,
      currentUser.value!.firstname,
      currentUser.value!.lastname,
      currentUser.value?.dateOfBirth,
      currentUser.value?.female,
    );

    return newTeam;
  }

  Future<Team> updateTeam(int teamId, String teamName, int categoryId) async {
    // APIサービスを使用してチームを更新
    final updatedTeam = await _apiService.updateTeam(teamId, teamName, categoryId);
    return updatedTeam;
  }

  Future<void> deleteTeam(int teamId) async {
    bool confirmDelete = await Get.dialog(
      AlertDialog(
        title: const Text('チーム削除の確認'),
        content: const Text('このチームとそのすべてのメンバーを削除しますか？この操作は取り消せません。'),
        actions: [
          TextButton(
            child: const Text('キャンセル'),
            onPressed: () => Get.back(result: false),
          ),
          TextButton(
            child: const Text('削除'),
            onPressed: () => Get.back(result: true),
          ),
        ],
      ),
    ) ?? false;

    if (confirmDelete) {
      try {
        // まず、チームのメンバーを全て削除
        await _apiService.deleteAllTeamMembers(teamId);

        // その後、チームを削除
        await _apiService.deleteTeam(teamId);

        // ローカルのチームリストを更新
        teams.removeWhere((team) => team.id == teamId);

        /*
        Get.snackbar(
          '成功',
          'チームとそのメンバーが削除されました',
          backgroundColor: Colors.green,
          colorText: Colors.white,
          snackPosition: SnackPosition.BOTTOM,
        );
         */

        // チームリスト画面に戻る
        Get.back();

      } catch (e) {
        print('Error deleting team and members: $e');
        Get.snackbar('エラー', 'チームとメンバーの削除に失敗しました');
      }
    }
  }

  Future<void> fetchTeamMembers(int teamId) async {
    try {
      isLoading.value = true;
      final members = await _apiService.getTeamMembers(teamId);
      teamMembers.assignAll(members);
      teamMembers.refresh(); // 明示的に更新を通知
    } catch (e) {
      error.value = 'メンバーの取得に失敗しました: $e';
      print('Error fetching team members: $e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> updateMember(teamId, User member) async {
    try {
      isLoading.value = true;
      await _apiService.updateTeamMember(teamId,member.id,  member.firstname,  member.lastname,  member.dateOfBirth, member.female);
      await fetchTeamMembers(selectedTeam.value!.id);
    } catch (e) {
      error.value = 'メンバーの更新に失敗しました: $e';
      print('Error updating member: $e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> deleteMember(int memberId, int teamId) async {
    try {
      isLoading.value = true;
      await _apiService.deleteTeamMember(teamId,memberId);
      await fetchTeamMembers(teamId);
    } catch (e) {
      error.value = 'メンバーの削除に失敗しました: $e';
      print('Error deleting member: $e');
    } finally {
      isLoading.value = false;
    }
  }


 // Future<void> addMember(User member, int teamId) async {
 //   try {
 //     isLoading.value = true;
 //     await _apiService.createTeamMember(teamId, member.email,  member.firstname,  member.lastname,  member.dateOfBirth);
 //     await fetchTeamMembers(teamId);
 //   } catch (e) {
 //     error.value = 'メンバーの追加に失敗しました: $e';
 //     print('Error adding member: $e');
 //   } finally {
 //     isLoading.value = false;
 //   }
 // }


  void updateTeamName(String value) {
    teamName.value = value;
  }

  void updateCategory(NewCategory? value) {
    if (value != null) {
      selectedCategory.value = value;
    }
  }
  //void updateCategory(NewCategory? value) {
  //  if (value != null) {
  //    selectedCategory.value = categories.firstWhere(
  //          (category) => category.id == value.id,
  //      orElse: () => value,
  //    );
  //  }
  //}

  Future<void> saveTeam() async {
    try {
      isLoading.value = true;
      if (selectedCategory.value == null) {
        throw Exception('カテゴリを選択してください');
      }

      if (selectedTeam.value == null) {
        await createTeam(teamName.value, selectedCategory.value!.id);
      } else {
        await updateTeam(selectedTeam.value!.id, teamName.value, selectedCategory.value!.id);
      }

      // サーバーから最新のデータを再取得
      await fetchTeams();
      update();  // UIを強制的に更新
    } catch (e) {
      error.value = 'チームの保存に失敗しました: $e';

    } finally {
      isLoading.value = false;
    }
  }


  Future<void> deleteSelectedTeam() async {
    if (selectedTeam.value != null) {
      await deleteTeam(selectedTeam.value!.id);
      selectedTeam.value = null;
    }
  }

  List<NewCategory> getFilteredCategories_old() {
    //List<User> teamMembers = getCurrentTeamMembers();
    return categories.where((category) {
      return isCategoryValid(category, teamMembers);
    }).toList();
  }

  List<NewCategory> getFilteredCategories() {
    if (teamMembers.isEmpty && currentUser.value != null) {
      // ソロの場合
      String baseCategory = currentUser.value!.female ? 'ソロ女子' : 'ソロ男子';
      return categories.where((c) => c.categoryName.startsWith(baseCategory)).toList();
    } else {
      bool hasElementaryOrYounger = teamMembers.any(isElementarySchoolOrYounger);
      String baseCategory = hasElementaryOrYounger ? 'ファミリー' : '一般';
      return categories.where((c) => c.categoryName.startsWith(baseCategory)).toList();
    }
  }

  bool isElementarySchoolOrYounger(User user) {
    final now = DateTime.now();
    final age = now.year - user.dateOfBirth!.year;
    return age <= 12;
  }

  bool isCategoryValid(NewCategory category, List<User> teamMembers) {
    int maleCount = teamMembers.where((member) => !member.female).length;
    int femaleCount = teamMembers.where((member) => member.female).length;
    int totalCount = teamMembers.length;

    bool isValidGender = category.female ? (femaleCount == totalCount) : true;
    bool isValidMemberCount = totalCount == category.numOfMember;
    bool isValidFamily = category.family ? areAllMembersFamily(teamMembers) : true;

    return isValidGender && isValidMemberCount && isValidFamily;
  }

  bool areAllMembersFamily(List<User> teamMembers) {
    // 家族かどうかを判断するロジック（例: 同じ姓を持つメンバーが2人以上いる場合は家族とみなす）
    Set<String> familyNames = teamMembers.map((member) => member.lastname).toSet();
    return familyNames.length < teamMembers.length;
  }


  Future<void> updateTeamComposition() async {
    NewCategory? oldCategory = selectedCategory.value;
    String? oldTime = oldCategory?.time;

    // メンバーリストの最新状態を取得
    await fetchTeamMembers(selectedTeam.value!.id);

    List<NewCategory> eligibleCategories = [];
    if (teamMembers.isEmpty || teamMembers.length == 1) {
      if (currentUser.value != null) {
        String baseCategory = currentUser.value!.female ? 'ソロ女子' : 'ソロ男子';
        eligibleCategories = categories.where((c) => c.baseCategory == baseCategory).toList();
      }
    } else {
      bool hasElementaryOrYounger = teamMembers.any(isElementarySchoolOrYounger);
      String baseCategory = hasElementaryOrYounger ? 'ファミリー' : '一般';
      eligibleCategories = categories.where((c) => c.baseCategory == baseCategory).toList();
    }

    // 同じ時間のカテゴリを優先的に選択
    NewCategory? newCategory = eligibleCategories.firstWhereOrNull((c) => c.time == oldTime);

    if (newCategory == null && eligibleCategories.isNotEmpty) {
      // 同じ時間のカテゴリがない場合、最初のカテゴリを選択
      newCategory = eligibleCategories.first;

      // 警告メッセージを表示
      Get.dialog(
        AlertDialog(
          title: Text('カテゴリ変更の通知'),
          content: Text('旧カテゴリの時間（$oldTime）と一致するカテゴリがないため、${newCategory.time ?? "時間指定なし"}を選択しました。'),
          actions: [
            TextButton(
              child: Text('OK'),
              onPressed: () => Get.back(),
            ),
          ],
        ),
      );
        }

    if (newCategory != null && oldCategory != newCategory) {
      selectedCategory.value = newCategory;

      // チームのカテゴリを更新
      if (selectedTeam.value != null) {
        try {
          final updatedTeam = await updateTeam(selectedTeam.value!.id, selectedTeam.value!.teamName, newCategory.id);
          selectedTeam.value = updatedTeam;

          // チームリストも更新
          final index = teams.indexWhere((team) => team.id == updatedTeam.id);
          if (index != -1) {
            teams[index] = updatedTeam;
          }

          // エントリーの締め切りチェック
          bool hasClosedEntries = await checkForClosedEntries(selectedTeam.value!.id);
          if (hasClosedEntries) {
            Get.dialog(
              AlertDialog(
                title: Text('警告'),
                content: Text('締め切りを過ぎたエントリーがあります。カテゴリ変更が必要な場合は事務局にお問い合わせください。'),
                actions: [
                  TextButton(
                    child: Text('OK'),
                    onPressed: () => Get.back(),
                  ),
                ],
              ),
            );
          } else {
            await checkAndHandleCategoryChange(oldCategory!, newCategory);
          }
        } catch (e) {
          print('Error updating team category: $e');
          Get.snackbar('エラー', 'チームのカテゴリ更新に失敗しました');
        }
      }
    }
  }

  Future<bool> checkForClosedEntries(int teamId) async {
    try {
      final entries = await _apiService.getEntries();
      return entries.any((entry) => !isEntryEditable(entry.event));
    } catch (e) {
      print('Error checking for closed entries: $e');
      return false;
    }
  }

  bool isEntryEditable(Event event) {
    return DateTime.now().isBefore(event.deadlineDateTime);
  }



  Future<void> updateTeamComposition_old() async {
    NewCategory? oldCategory = selectedCategory.value;
    String? oldTime = oldCategory?.time;

    // メンバーリストの最新状態を取得
    await fetchTeamMembers(selectedTeam.value!.id);

    List<NewCategory> eligibleCategories = [];
    if (teamMembers.isEmpty) {
      if (currentUser.value != null) {
        String baseCategory = currentUser.value!.female ? 'ソロ女子' : 'ソロ男子';
        eligibleCategories = categories.where((c) => c.baseCategory == baseCategory).toList();
      }
    } else {
      bool hasElementaryOrYounger = teamMembers.any(isElementarySchoolOrYounger);
      String baseCategory = hasElementaryOrYounger ? 'ファミリー' : '一般';
      eligibleCategories = categories.where((c) => c.baseCategory == baseCategory).toList();
    }

    // 同じ時間のカテゴリを優先的に選択
    NewCategory? newCategory = eligibleCategories.firstWhereOrNull((c) => c.time == oldTime);

    if (newCategory == null && eligibleCategories.isNotEmpty) {
      // 同じ時間のカテゴリがない場合、最初のカテゴリを選択
      newCategory = eligibleCategories.first;

      // 警告メッセージを表示
      Get.dialog(
        AlertDialog(
          title: Text('カテゴリ変更の通知'),
          content: Text('旧カテゴリの時間（$oldTime）と一致するカテゴリがないため、${newCategory.time ?? "時間指定なし"}を選択しました。'),
          actions: [
            TextButton(
              child: Text('OK'),
              onPressed: () => Get.back(),
            ),
          ],
        ),
      );
        }

    if (newCategory != null && oldCategory != newCategory) {
      selectedCategory.value = newCategory;

      // チームのカテゴリを更新
      if (selectedTeam.value != null) {
        try {
          final updatedTeam = await updateTeam(selectedTeam.value!.id, selectedTeam.value!.teamName, newCategory.id);
          selectedTeam.value = updatedTeam;

          // チームリストも更新
          final index = teams.indexWhere((team) => team.id == updatedTeam.id);
          if (index != -1) {
            teams[index] = updatedTeam;
          }
        } catch (e) {
          print('Error updating team category: $e');
          Get.snackbar('エラー', 'チームのカテゴリ更新に失敗しました');
        }
      }

      await checkAndHandleCategoryChange(oldCategory!, newCategory);
    }
  }

  // メンバーの追加後に呼び出すメソッド
  Future<void> addMember(User newMember) async {
    try {
      await _apiService.createTeamMember(selectedTeam.value!.id, newMember.email, newMember.firstname, newMember.lastname, newMember.dateOfBirth, newMember.female);
      await updateTeamComposition();
    } catch (e) {
      print('Error adding member: $e');
      Get.snackbar('エラー', 'メンバーの追加に失敗しました');
    }
  }

  // メンバーの削除後に呼び出すメソッド
  Future<void> removeMember(int memberId) async {
    try {
      await _apiService.deleteTeamMember(selectedTeam.value!.id, memberId);

      // selectedTeamからメンバーを削除
      if (selectedTeam.value != null) {
        selectedTeam.value!.members.removeWhere((member) => member.id == memberId);
        selectedTeam.refresh();
      }

      // メンバー削除後にチーム構成を更新
      await updateTeamComposition();

      // teamMembersを更新
      await fetchTeamMembers(selectedTeam.value!.id);
    } catch (e) {
      print('Error removing member: $e');
      Get.snackbar('エラー', 'メンバーの削除に失敗しました');
    }
  }

  Future<void> checkAndHandleCategoryChange(NewCategory oldCategory, NewCategory newCategory) async {
    try {
      if (selectedTeam.value == null) {
        print('No team selected');
        return;
      }

      // エントリーの存在を確認
      bool hasEntries = await checkIfTeamHasEntries(selectedTeam.value!.id);

      if (hasEntries) {
        bool shouldCreateNewTeam = await Get.dialog<bool>(
          CategoryChangeDialog(
            oldCategory: oldCategory.categoryName,
            newCategory: newCategory.categoryName,
          ),
        ) ?? false;

        if (shouldCreateNewTeam) {
          await createNewTeamWithCurrentMembers();
        } else {
          await updateEntriesWithNewCategory();
        }
      }else{
        // エントリーが存在しない場合は、カテゴリの更新のみを行う
        await updateTeamCategory(newCategory);
      }
    } catch (e) {
      print('Error in checkAndHandleCategoryChange: $e');
      Get.snackbar('エラー', 'カテゴリ変更の処理中にエラーが発生しました');
    }
  }

  Future<bool> checkIfTeamHasEntries(int teamId) async {
    try {
      final entries = await _apiService.getTeamEntries(teamId);
      return entries.isNotEmpty;
    } catch (e) {
      print('Error checking if team has entries: $e');
      return false;
    }
  }

  Future<void> updateTeamCategory(NewCategory newCategory) async {
    try {
      if (selectedTeam.value != null) {
        final updatedTeam = await updateTeam(selectedTeam.value!.id, selectedTeam.value!.teamName, newCategory.id);
        selectedTeam.value = updatedTeam;

        // チームリストも更新
        final index = teams.indexWhere((team) => team.id == updatedTeam.id);
        if (index != -1) {
          teams[index] = updatedTeam;
        }

        Get.snackbar('成功', 'チームのカテゴリを更新しました');
      }
    } catch (e) {
      print('Error updating team category: $e');
      Get.snackbar('エラー', 'チームのカテゴリ更新に失敗しました');
    }
  }

  Future<void> fetchTeamEntries(int teamId) async {
    try {
      final fetchedEntries = await _apiService.getEntries();
      teamEntries.assignAll(fetchedEntries);
    } catch (e) {
      print('Error fetching team entries: $e');
      teamEntries.clear(); // エラーが発生した場合、エントリーリストをクリア
      //Get.snackbar('エラー', 'チームのエントリー取得に失敗しました');
    }
  }


  Future<void> createNewTeamWithCurrentMembers() async {
    String newTeamName = '${selectedTeam.value!.teamName}_${DateTime.now().millisecondsSinceEpoch}';

    try {
      Team newTeam = await _apiService.createTeam(newTeamName, selectedCategory.value!.id);

      for (var member in teamMembers) {
        await _apiService.createTeamMember(
          newTeam.id,
          member.email,
          member.firstname,
          member.lastname,
          member.dateOfBirth,
          member.female,
        );
      }

      Get.offNamed(AppPages.TEAM_DETAIL, arguments: {'mode': 'edit', 'team': newTeam});
    } catch (e) {
      print('Error creating new team: $e');
      Get.snackbar('エラー', '新しいチームの作成に失敗しました');
    }
  }

  Future<void> updateEntriesWithNewCategory() async {
    try {
      for (var entry in teamEntries) {
        //await _apiService.updateEntry(entry.id, selectedCategory.value!.id);
        final updatedEntry = await _apiService.updateEntry(
          entry.id,
          entry.team.id,
          entry.event.id,
          selectedCategory.value!.id,
          entry.date!,
          entry.zekkenNumber,
        );
      }
      Get.snackbar('成功', 'エントリーのカテゴリを更新しました');
    } catch (e) {
      print('Error updating entries: $e');
      Get.snackbar('エラー', 'エントリーの更新に失敗しました');
    }
  }

  void updateCurrentUserGender(bool isFemale) {
    if (currentUser.value != null) {
      currentUser.value!.female = isFemale;
      updateTeamComposition();
    }
  }


}