import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:o2oa_all_platform/common/extension/index.dart';

import '../../../../common/api/index.dart';
import '../../../../common/models/index.dart';
import '../../../../common/utils/index.dart';
import '../../../../common/widgets/index.dart';
import '../calendar_const.dart';
import '../calendar_list/index.dart';
import 'index.dart';

class CreateCalendarEventController extends GetxController {
  CreateCalendarEventController();

  final state = CreateCalendarEventState();
  final titleController = TextEditingController();
  final commentController = TextEditingController();
  final updateTips = [
    'calendar_event_update_single_tip'.tr,
    'calendar_event_update_after_tip'.tr,
    'calendar_event_update_all_tip'.tr
  ];
  final deleteTips = [
    'calendar_event_delete_single_tip'.tr,
    'calendar_event_delete_after_tip'.tr,
    'calendar_event_delete_all_tip'.tr
  ];

  // 更新相关
  EventInfo? _event;

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    final map = Get.arguments;
    if (map != null &&
        map["eventInfo"] != null &&
        map["eventInfo"] is EventInfo) {
      final event = map["eventInfo"] as EventInfo;
      _event = event;
      parseEvent(event);
      state.isUpdate = true;
    } else {
      final now = DateTime.now();
      state.startDate = now.ymd();
      state.startTime = now.hm();
      state.endDate = now.ymd();
      state.endTime = now.addHours(1).hm();
      state.eventColor = O2Calendar.deepColors[0];
      state.isUpdate = false;
    }
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
  }

  /// dispose 释放内存
  @override
  void dispose() {
    super.dispose();
  }

  /// 修改的时候 对象解析
  void parseEvent(EventInfo event) {
    if (event.calendarId != null) {
      _getCalendarInfo(event.calendarId!);
    }
    final start = DateTime.tryParse(event.startTime ?? '');
    if (start != null) {
      state.startDate = start.ymd();
      state.startTime = start.hm();
    }
    final end = DateTime.tryParse(event.endTime ?? '');
    if (end != null) {
      state.endDate = end.ymd();
      state.endTime = end.hm();
    }
    titleController.text = event.title ?? '';
    commentController.text = event.comment ?? '';
    state.eventColor = event.color ?? O2Calendar.deepColors[0];
    state.allDay = event.isAllDayEvent ?? false;
    _rruleDecode(event.recurrenceRule ?? '');
    _transBackRemindConfig(event.valarmTimeConfig ?? '');
  }

  _getCalendarInfo(String id) async {
    final result = await CalendarAssembleControlService.to.getCalendar(id);
    if (result != null) {
      state.calendar.value = result;
    }
  }

  /// 更新日程
  void updateEvent() async {
    final eventInfo = checkNewEvent();
    if (eventInfo == null) {
      return;
    }
    if (_event == null || _event?.id == null || _event?.id?.isEmpty == true) {
      return;
    }
    eventInfo.id = _event?.id;
    // 是否有重复规则
    if (_event?.recurrenceRule?.isNotEmpty == true) {
      final context = Get.context;
      if (context == null) {
        return;
      }
      List<Widget> widgets = [];
      var i = -1;
      for (var element in updateTips) {
        i++;
        final tag = i;
        widgets.add(ListTile(
              title: Text(element),
              onTap: () {
                Navigator.pop(context);
                if (tag == 0) {
                  _updateSingle(eventInfo);
                } else if (tag == 1) {
                  _updateAfter(eventInfo);
                } else {
                  _updateAll(eventInfo);
                }
              },
            ));
      }
      
      O2UI.showBottomSheetWithCancel(
          context,
          widgets);
    } else {
      _updateSingle(eventInfo);
    }
  }

  void _updateSingle(EventInfo eventInfo) async {
    final result =
        await CalendarAssembleControlService.to.updateEventSingle(eventInfo);
    if (result != null) {
      Get.back();
    }
  }

  void _updateAfter(EventInfo eventInfo) async {
    final result =
        await CalendarAssembleControlService.to.updateEventAfter(eventInfo);
    if (result != null) {
      Get.back();
    }
  }

  void _updateAll(EventInfo eventInfo) async {
    final result =
        await CalendarAssembleControlService.to.updateEventAll(eventInfo);
    if (result != null) {
      Get.back();
    }
  }

  void deleteEvent() async {
    if (_event == null || _event?.id == null || _event?.id?.isEmpty == true) {
      return;
    }
    // 是否有重复规则
    if (_event?.recurrenceRule?.isNotEmpty == true) {
      final context = Get.context;
      if (context == null) {
        return;
      }
      List<Widget> widgets = [];
      var i = -1;
      for (var element in deleteTips) {
        i++;
        final tag = i;
        widgets.add(ListTile(
              title: Text(element),
              onTap: () {
                Navigator.pop(context);
                if (tag == 0) {
                  _deleteSingle(_event!.id!);
                } else if (tag == 1) {
                  _deleteAfter(_event!.id!);
                } else {
                  _deleteAll(_event!.id!);
                }
              },
            ));
      }
      
      O2UI.showBottomSheetWithCancel(
          context,
          widgets);
    } else {
      _deleteSingle(_event!.id!);
    }
  }

  void _deleteSingle(String id) async {
    final result =
        await CalendarAssembleControlService.to.deleteEventSingle(id);
    if (result != null) {
      Get.back();
    }
  }

  void _deleteAfter(String id) async {
    final result =
        await CalendarAssembleControlService.to.deleteEventAfter(id);
    if (result != null) {
      Get.back();
    }
  }

  void _deleteAll(String id) async {
    final result =
        await CalendarAssembleControlService.to.deleteEventAll(id);
    if (result != null) {
      Get.back();
    }
  }
  /// 检查表单数据 并返回日程对象
  EventInfo? checkNewEvent() {
    if (titleController.text.isEmpty) {
      Loading.showError('calendar_event_form_title_hint'.tr);
      return null;
    }
    if (state.calendar.value == null) {
      Loading.showError('calendar_event_form_calendar_hint'.tr);
      return null;
    }
    String start = state.startDate;
    String end = state.endDate;
    if (!state.allDay) {
      start = '$start ${state.startTime}:00';
      end = '$end ${state.endTime}:00';
    } else {
      start = '$start 00:00:00';
      end = '$end 23:59:59';
    }
    if (start.compareTo(end) > 0) {
      Loading.showError('calendar_event_form_error_start_bigger_end'.tr);
      return null;
    }
    if (state.repeat == 'WEEKLY' && state.weekDayKeys.isEmpty) {
      Loading.showError('calendar_event_form_repeat_week_day_empty'.tr);
      return null;
    }
    EventInfo eventInfo = EventInfo();
    eventInfo.calendarId = state.calendar.value?.id;
    eventInfo.title = titleController.text;
    eventInfo.isAllDayEvent = state.allDay;
    eventInfo.startTime = start;
    eventInfo.endTime = end;
    eventInfo.color = state.eventColor;
    eventInfo.recurrenceRule = _rruleEncode(state.repeat,
        repeatWeekList: state.weekDayKeys,
        untilDate: state.repeatEndDate.isEmpty ? 'NONE' : state.repeatEndDate);
    eventInfo.comment = commentController.text;
    eventInfo.valarmTimeConfig = _remindDecode(state.remind);
    return eventInfo;
  }

  /// 保存日程
  void saveEvent() async {
    final eventInfo = checkNewEvent();
    if (eventInfo == null) {
      return;
    }
    final result = await CalendarAssembleControlService.to.saveEvent(eventInfo);
    if (result != null) {
      Get.back();
    }
  }

  /// 提醒规则解析
  void _transBackRemindConfig(String remindConfig) {
    if (remindConfig.isEmpty) {
      return;
    }
    final arr = remindConfig.split(",");
    var reValue = "";
    for (var i = 0; i < arr.length; i++) {
      final time = arr[i];
      if (time.isNotEmpty && time != '0') {
        if (i == 0) {
          reValue = "${time}_d";
          break;
        }
        if (i == 1) {
          reValue = "${time}_h";
          break;
        }
        if (i == 2) {
          reValue = "${time}_m";
          break;
        }
        if (i == 3) {
          reValue = "${time}_s";
          break;
        }
      }
    }
    if (reValue.isEmpty) {
      state.remind = 'NONE';
    } else {
      state.remind = reValue;
    }
  }

  /// 重复规则解析
  void _rruleDecode(String rrule) {
    if (rrule.isNotEmpty) {
      final ruleArr = rrule.split(";");
      for (var element in ruleArr) {
        final stageArray = element.split("=");
        if (stageArray.isNotEmpty) {
          final key = stageArray[0];
          if (key == "FREQ") {
            final value = stageArray[1];
            if (value.isEmpty) {
              state.repeat = "NONE";
            } else {
              state.repeat = value;
            }
          } else if (key == "BYDAY") {
            state.weekDayKeys.addAll(stageArray[1].split(","));
          } else if (key == "UNTIL") {
            var untilDate = stageArray[1].substring(0, 8);
            state.repeatEndDate = DateTime.tryParse(untilDate)?.ymd() ?? '';
          }
        }
      }
    }
  }

  /// 重复规则编码
  String _rruleEncode(String freq,
      {List<String> repeatWeekList = const [], String untilDate = 'NONE'}) {
    if (freq.isEmpty || freq == 'NONE') {
      return '';
    }
    var mFreq = "FREQ=$freq";
    var date = '';
    if (untilDate.isNotEmpty && untilDate != 'NONE') {
      date = DateTime.tryParse(untilDate)?.ymd(needHyphen: false) ?? '';
    }
    if (date.isNotEmpty) {
      mFreq = "$mFreq;UNTIL=${date}T000000Z";
    }
    if (freq == "WEEKLY" && repeatWeekList.isNotEmpty) {
      mFreq = "$mFreq;BYDAY=${repeatWeekList.join(',')}";
    }
    return mFreq;
  }

  /// 提醒转化函数
  String _remindDecode(String remind) {
    var array = ["0", "0", "0", "0"];
    if (remind.isNotEmpty && remind != 'NONE') {
      final split = remind.split("_");
      if (split[1] == 's') {
        array[3] = split[0];
      } else if (split[1] == 'm') {
        array[2] = split[0];
      } else if (split[1] == 'h') {
        array[1] = split[0];
      }
    }
    return array.join(",");
  }

  /// 选择日历
  void pickCalendar() async {
    final result = await CalendarListPage.open(isSelectMode: true);
    if (result != null && result is CalendarInfo) {
      state.calendar.value = result;
    }
  }

  /// 选择颜色
  void chooseEventColor(String color) {
    OLogger.d('choose color $color');
    state.eventColor = color;
  }

  /// 选择日期
  void selectStartDate() async {
    final context = Get.context;
    if (context == null) return;

    DateTime? initDate = DateTime.tryParse(state.startDate);
    initDate ??= DateTime.now();
    final result = await showDatePicker(
        context: context,
        initialDate: initDate,
        firstDate: initDate.addYears(-10),
        lastDate: initDate.addYears(10));
    if (result != null) {
      state.startDate = result.ymd();
    }
  }

  /// 选择时间
  void selectStartTime() async {
    final context = Get.context;
    if (context == null) return;
    DateTime? initDate =
        DateTime.tryParse('${state.startDate} ${state.startTime}:00');
    initDate ??= DateTime.now();
    TimeOfDay initTime =
        TimeOfDay(hour: initDate.hour, minute: initDate.minute);
    final startTime =
        await showTimePicker(context: context, initialTime: initTime);
    if (startTime != null) {
      final startHour =
          startTime.hour > 9 ? '${startTime.hour}' : '0${startTime.hour}';
      final startMinute =
          startTime.minute > 9 ? '${startTime.minute}' : '0${startTime.minute}';
      state.startTime = '$startHour:$startMinute';
    }
  }

  void selectEndDate() async {
    final context = Get.context;
    if (context == null) return;

    DateTime? initDate = DateTime.tryParse(state.endDate);
    initDate ??= DateTime.now();
    final result = await showDatePicker(
        context: context,
        initialDate: initDate,
        firstDate: initDate.addYears(-10),
        lastDate: initDate.addYears(10));
    if (result != null) {
      state.endDate = result.ymd();
    }
  }

  void selectEndTime() async {
    final context = Get.context;
    if (context == null) return;
    DateTime? initDate =
        DateTime.tryParse('${state.endDate} ${state.endTime}:00');
    initDate ??= DateTime.now();
    TimeOfDay initTime =
        TimeOfDay(hour: initDate.hour, minute: initDate.minute);
    final endTime =
        await showTimePicker(context: context, initialTime: initTime);
    if (endTime != null) {
      final startHour =
          endTime.hour > 9 ? '${endTime.hour}' : '0${endTime.hour}';
      final startMinute =
          endTime.minute > 9 ? '${endTime.minute}' : '0${endTime.minute}';
      state.endTime = '$startHour:$startMinute';
    }
  }

  /// 选择提醒方式
  void selectRemind() {
    final context = Get.context;
    if (context == null) return;
    final widgets = O2Calendar.remindOptions.entries
        .map((e) => ListTile(
              onTap: () {
                Navigator.pop(context);
                state.remind = e.key;
              },
              title: Align(
                alignment: Alignment.center,
                child: Text(e.value,
                    style: Theme.of(context).textTheme.bodyMedium),
              ),
            ))
        .toList();
    O2UI.showBottomSheetLongList(context, widgets);
  }

  /// 选择重复方式
  void selectRepeat() {
    final context = Get.context;
    if (context == null) return;
    final widgets = O2Calendar.repeatOptions.entries
        .map((e) => ListTile(
              onTap: () {
                Navigator.pop(context);
                state.repeat = e.key;
              },
              title: Align(
                alignment: Alignment.center,
                child: Text(e.value,
                    style: Theme.of(context).textTheme.bodyMedium),
              ),
            ))
        .toList();
    O2UI.showBottomSheetWithCancel(context, widgets);
  }

  /// 是否全天事件
  void changeAllDay(bool allDay) {
    state.allDay = allDay;
  }

  /// 重复事件的截止日期
  void selectRepeatEndDate() async {
    final context = Get.context;
    if (context == null) return;

    DateTime? initDate = DateTime.tryParse(state.repeatEndDate);
    initDate ??= DateTime.now();
    final result = await showDatePicker(
        context: context,
        initialDate: initDate,
        firstDate: initDate.addYears(-10),
        lastDate: initDate.addYears(10));
    if (result != null) {
      state.repeatEndDate = result.ymd();
    }
  }

  /// 周重复 选择周几
  void chooseWeekDay(String weekDayKey) {
    if (state.weekDayKeys.contains(weekDayKey)) {
      state.weekDayKeys.remove(weekDayKey);
    } else {
      state.weekDayKeys.add(weekDayKey);
    }
  }
}
