import 'dart:io';
import 'dart:ui';
import 'package:electronic_assistant/utils/pair.dart';
import 'package:electronic_assistant/utils/toast_util.dart';
import 'package:get/get.dart';
import 'package:just_audio/just_audio.dart';
import 'package:uuid/uuid.dart';
import '../data/bean/talks.dart';
import '../data/repositories/talk_repository.dart';
import '../dialog/loading_dialog.dart';
import '../module/talk/view.dart';
import '../resource/string.gen.dart';
import 'audio_picker_utils.dart';
import 'package:path_provider/path_provider.dart';

import 'common_utils.dart';
import 'error_handler.dart';

class FileUploadCheckHelper {
  FileUploadCheckHelper._();

  static bool isAllowAudioFile(String path) {
    try {
      String ext = path.split('.').last;
      return AudioPickerUtils.allowFileType.contains(ext);
    } catch (e) {
      return false;
    }
  }

  static Future<void> choicePlatformLocalFileAndCreateOrder(
      {VoidCallback? choiceSuccessCallback}) async {
    TalkBean? bean;
    try {
      Pair<File, Duration>? pair =
          await FileUploadCheckHelper.pickerPlatformFile();
      if (pair == null) {
        //未选择文件
        return;
      }
      LoadingDialog.show(StringName.fileImporting.tr);
      bean = await FileUploadCheckHelper.createTalkFromLocalFile(
          pair.first, pair.second);
      choiceSuccessCallback?.call();
      TalkPage.start(bean);
    } catch (e) {
      if (e is PickerException) {
        ToastUtil.showToast(e.message);
      } else {
        ErrorHandler.toastError(e, message: StringName.fileImportFail.tr);
      }
    } finally {
      LoadingDialog.hide();
    }
  }

  static Future<Duration> checkCanUpload(File file) async {
    //文件不能超过500M
    if (file.lengthSync() > 500 * 1024 * 1024) {
      throw PickerException(StringName.fileChoiceSizeLimit.tr);
    }
    AudioPlayer? player;
    try {
      player = AudioPlayer();
      player.setAudioSource(AudioSource.uri(file.uri));
      Duration? duration = await player.durationStream
          .firstWhere((duration) => duration != null);
      if (duration == null) {
        throw PickerException(StringName.fileAudioDurationCannotObtained.tr);
      }
      if (duration.inSeconds < 3) {
        throw PickerException(StringName.recordingDurationCannotLessThan3s.tr);
      }
      //录音时长不能超过5小时
      if (duration.inHours > 5) {
        throw PickerException(StringName.fileAudioDurationLimit.tr);
      }
      return duration;
    } finally {
      player?.dispose();
    }
  }

  static Future<Pair<File, Duration>?> pickerPlatformFile() async {
    File? file = await AudioPickerUtils.pickSingleFileByPlatform();
    if (file == null) {
      return null;
    }
    Duration duration = await checkCanUpload(file);
    return Pair(file, duration);
  }

  static Future<TalkBean> createTalkFromLocalFile(
      File file, Duration duration) async {
    TalkBean bean = await talkRepository.talkCreate(
        const Uuid().v4(), duration.inSeconds,
        uploadType: FileUploadType.local);

    String childDirName = bean.id;
    Directory dir = await getChoiceUploadDir(childDirName);

    await moveFileToDirectory(file, dir);
    return bean;
  }

  static Future<Directory> getChoiceUploadDir(String talkId) async {
    Directory documentDir = await getApplicationDocumentsDirectory();
    return Directory("${documentDir.path}/.atmob/choice/$talkId");
  }

  static Future<File?> getChoiceUploadFile(String talkId) async {
    Directory dir = await getChoiceUploadDir(talkId);
    if (!dir.existsSync()) {
      return null;
    }
    List<FileSystemEntity> list = dir.listSync();
    if (list.isEmpty) {
      return null;
    }
    return list.first as File;
  }

  static Future<void> moveFileToDirectory(File file, Directory dir) async {
    if (!dir.existsSync()) {
      dir.createSync(recursive: true);
    }
    String newFilePath = '${dir.path}/${file.uri.pathSegments.last}';
    file.renameSync(newFilePath);
  }

  static const String _uploadServerAudioTag = '_&&@@##_';

  //拼接设备ID用于标识
  static String joinUploadServerAudioTag(String id) {
    return '${getDeviceId()}$_uploadServerAudioTag$id';
  }

  static String? getLocalAudioId(String? tag) {
    if (tag == null || tag.isEmpty) {
      return null;
    }
    if (!tag.contains(_uploadServerAudioTag)) {
      return null;
    }
    List<String> audioTag = tag.split(_uploadServerAudioTag);
    if (audioTag.first != getDeviceId()) {
      return null;
    }
    return tag.split(_uploadServerAudioTag).last;
  }
}

class PickerException implements Exception {
  final String message;

  PickerException(this.message);

  @override
  String toString() {
    return 'PickerException: $message';
  }
}
