// lib/entry/entry_controller.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:gifunavi/model/entry.dart';
import 'package:gifunavi/model/event.dart';
import 'package:gifunavi/model/team.dart';
import 'package:gifunavi/model/category.dart';
import 'package:gifunavi/services/api_service.dart';

import '../index/index_controller.dart';
import 'package:timezone/timezone.dart' as tz;

class EntryController extends GetxController {
  late ApiService _apiService;

  final entries = <Entry>[].obs;
  final events = <Event>[].obs;
  final teams = <Team>[].obs;
  final categories = <NewCategory>[].obs;

  final selectedEvent = Rx<Event?>(null);
  final selectedTeam = Rx<Team?>(null);
  final selectedCategory = Rx<NewCategory?>(null);
  final selectedDate = Rx<DateTime?>(null);

  final currentEntry = Rx<Entry?>(null);
  final isLoading = true.obs;

  @override
  void onInit() async {
    super.onInit();
    await initializeApiService();
    await loadInitialData();
  }

  Future<void> initializeApiService() async {
    try {
      _apiService = await Get.putAsync(() => ApiService().init());
    } catch (e) {
      print('Error initializing ApiService: $e');
      Get.snackbar('Error', 'Failed to initialize API service');
    }
  }

  Future<void> loadInitialData() async {
    try {
      isLoading.value = true;
      await Future.wait([
        fetchEntries(),
        fetchEvents(),
        fetchTeams(),
        fetchCategories(),
      ]);
      if (Get.arguments != null && Get.arguments['entry'] != null) {
        currentEntry.value = Get.arguments['entry'];
        initializeEditMode(currentEntry.value!);
      } else {
        // 新規作成モードの場合、最初のイベントを選択
        if (events.isNotEmpty) {
          selectedEvent.value = events.first;
          selectedDate.value = events.first.startDatetime;
        }
      }
    } catch(e) {
      print('Error initializing data: $e');
      Get.snackbar('Error', 'Failed to load initial data');
    } finally {
      isLoading.value = false;
    }
  }


  void initializeEditMode(Entry entry) {
    currentEntry.value = entry;
    selectedEvent.value = entry.event;
    selectedTeam.value = entry.team;
    selectedCategory.value = entry.category;
    selectedDate.value = entry.date;
  }

  void updateEvent(Event? value) {
    selectedEvent.value = value;
    if (value != null) {
      // イベント変更時に日付を調整
      if (selectedDate.value == null ||
          selectedDate.value!.isBefore(value.startDatetime) ||
          selectedDate.value!.isAfter(value.endDatetime)) {
        selectedDate.value = value.startDatetime;
      }
    }
  }

  void updateTeam(Team? value) {
    selectedTeam.value = value;
    if (value != null) {
      selectedCategory.value = value.category;
    }
  }
  //void updateTeam(Team? value) => selectedTeam.value = value;
  void updateCategory(NewCategory? value) => selectedCategory.value = value;
  //void updateDate(DateTime value) => selectedDate.value = value;
  void updateDate(DateTime value) {
    selectedDate.value = tz.TZDateTime.from(value, tz.getLocation('Asia/Tokyo'));
  }
  /*
  void updateDate(DateTime value){
    selectedDate.value = DateFormat('yyyy-MM-dd').format(value!) as DateTime?;
  }

   */

  void _initializeEntryData() {
    if (currentEntry.value != null) {
      selectedEvent.value = currentEntry.value!.event;
      selectedTeam.value = currentEntry.value!.team;
      selectedCategory.value = currentEntry.value!.category;
      selectedDate.value = currentEntry.value!.date;
    }
  }

  Future<void> fetchEntries() async {
    try {
      final fetchedEntries = await _apiService.getEntries();
      entries.assignAll(fetchedEntries);
    } catch (e) {
      print('Error fetching entries: $e');
      Get.snackbar('Error', 'Failed to fetch entries');
    }
  }

  Future<void> fetchEvents() async {
    try {
      final fetchedEvents = await _apiService.getEvents();
      events.assignAll(fetchedEvents.map((event) {
        // end_dateの7日前を締め切りとして設定
        final deadlineDateTime = event.endDatetime.subtract(const Duration(days: 7));
        return Event(
          id: event.id,
          eventName: event.eventName,
          startDatetime: event.startDatetime,
          endDatetime: event.endDatetime,
          deadlineDateTime: deadlineDateTime,
        );
      }).toList());
    } catch (e) {
      print('Error fetching events: $e');
      Get.snackbar('Error', 'Failed to fetch events');
    }
  }

  Future<void> fetchEvents_old() async {
    try {
      final fetchedEvents = await _apiService.getEvents();
      events.assignAll(fetchedEvents);
    } catch (e) {
      print('Error fetching events: $e');
      Get.snackbar('Error', 'Failed to fetch events');
    }
  }

  Future<void> fetchTeams() async {
    try {
      final fetchedTeams = await _apiService.getTeams();
      teams.assignAll(fetchedTeams);
    } catch (e) {
      print('Error fetching teams: $e');
      Get.snackbar('Error', 'Failed to fetch team');
    }
  }

  Future<void> fetchCategories() async {
    try {
      final fetchedCategories = await _apiService.getCategories();
      categories.assignAll(fetchedCategories);
    } catch (e) {
      print('Error fetching categories: $e');
      Get.snackbar('Error', 'Failed to fetch categories');
    }
  }

  Future<void> createEntry() async {
    if (selectedEvent.value == null || selectedTeam.value == null ||
        selectedCategory.value == null || selectedDate.value == null) {
      Get.snackbar('Error', 'Please fill all fields');
      return;
    }
    try {
      isLoading.value = true;
      // Get zekken number
      final updatedCategory = await _apiService.getZekkenNumber(selectedCategory.value!.id);
      final zekkenNumber = updatedCategory.categoryNumber.toString();

      // selectedDate.value に 9時間を加えてJSTのオフセットを適用
      final jstDate = selectedDate.value!.add(const Duration(hours: 9));

      final newEntry = await _apiService.createEntry(
        selectedTeam.value!.id,
        selectedEvent.value!.id,
        selectedCategory.value!.id,
        jstDate, // JSTオフセットが適用された日付を使用
        zekkenNumber,
      );
      entries.add(newEntry);
      Get.back();
    } catch (e) {
      print('Error creating entry: $e');
      Get.snackbar('Error', '$e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> updateEntryAndRefreshMap() async {
    await updateEntry();

    // エントリーが正常に更新された後、マップをリフレッシュ
    final indexController = Get.find<IndexController>();
    final eventCode = currentEntry.value?.event.eventName ?? '';
    indexController.reloadMap(eventCode);
  }

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

  Future<void> updateEntry() async {
    if (currentEntry.value == null) {
      Get.snackbar('Error', 'No entry selected for update');
      return;
    }

    if (!isEntryEditable(currentEntry.value!.event)) {
      Get.dialog(
        AlertDialog(
          title: Text('エントリー変更不可'),
          content: Text('締め切りを過ぎているため、エントリーの変更はできません。変更が必要な場合は事務局にお問い合わせください。'),
          actions: [
            TextButton(
              child: Text('OK'),
              onPressed: () => Get.back(),
            ),
          ],
        ),
      );
      return;
    }

    try {
      isLoading.value = true;
      final updatedEntry = await _apiService.updateEntry(
        currentEntry.value!.id,
        currentEntry.value!.team.id,
        selectedEvent.value!.id,
        selectedCategory.value!.id,
        selectedDate.value!,
        currentEntry.value!.zekkenNumber,
      );
      final index = entries.indexWhere((entry) => entry.id == updatedEntry.id);
      if (index != -1) {
        entries[index] = updatedEntry;
      }
      Get.back();
    } catch (e) {
      print('Error updating entry: $e');
      Get.snackbar('Error', 'Failed to update entry');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> updateEntryCategory(int entryId, int newCategoryId) async {
    try {
      //await _apiService.updateEntryCategory(entryId, newCategoryId);
      final updatedEntry = await _apiService.updateEntry(
        currentEntry.value!.id,
        currentEntry.value!.team.id,
        selectedEvent.value!.id,
        newCategoryId,
        currentEntry.value!.date!,
        currentEntry.value!.zekkenNumber,
      );
      await fetchEntries();
    } catch (e) {
      print('Error updating entry category: $e');
      Get.snackbar('エラー', 'エントリーのカテゴリ更新に失敗しました');
    }
  }

  Future<void> deleteEntry() async {
    if (currentEntry.value == null) {
      Get.snackbar('Error', 'No entry selected for deletion');
      return;
    }
    try {
      isLoading.value = true;
      await _apiService.deleteEntry(currentEntry.value!.id);
      entries.removeWhere((entry) => entry.id == currentEntry.value!.id);
      Get.back();
    } catch (e) {
      print('Error deleting entry: $e');
      Get.snackbar('Error', 'Failed to delete entry');
    } finally {
      isLoading.value = false;
    }
  }


  bool isOwner() {
    // Implement logic to check if the current user is the owner of the entry
    return true; // Placeholder
  }
}