import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:isekai_wiki/api/base_api.dart';
import 'package:isekai_wiki/api/mw/mw_api.dart';
import 'package:isekai_wiki/api/mw/user.dart';
import 'package:isekai_wiki/api/response/mugenapp.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/styles.dart';
import 'package:isekai_wiki/utils/dialog.dart';
import 'package:isekai_wiki/utils/error.dart';
import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class UserInfo {
  int userId;
  String userName;
  String? nickName;
  Map<int, String>? avatarUrlSet;

  UserInfo({
    required this.userId,
    required this.userName,
    this.nickName,
    this.avatarUrlSet,
  });

  factory UserInfo.fromJson(Map<String, dynamic> json) =>
      _$UserInfoFromJson(json);

  Map<String, dynamic> toJson() => _$UserInfoToJson(this);
}

class UserController extends GetxController {
  bool _ignoreSave = false;

  var authProcessing = false.obs;

  var loginRequestToken = "".obs;

  var userId = 0.obs;

  var userName = "".obs;
  var nickName = "".obs;
  var avatarUrlSet = RxMap<int, String>({});

  bool get isLoggedIn {
    return userId.value > 0;
  }

  String get displayName {
    return nickName.isNotEmpty ? nickName.string : userName.string;
  }

  @override
  void onInit() async {
    super.onInit();

    loadFromStorage();
    updateProfile();

    ever(loginRequestToken, (String token) {
      saveToStorage();
    });
  }

  /// 更新用户资料,并检测登录状态
  Future<void> updateProfile() async {
    try {
      var userInfoMWRes = await MWApiUser.getCurrentUserInfo();

      var userInfoRes = userInfoMWRes.data;

      if (userInfoRes.userinfo.id == 0) {
        // 登录状态已失效,提示用户
        // 由于刷新用户信息可能出现在首页加载完成之前,这里应该需要一个消息列表
        //   把加载中的错误放在消息列表中,首页加载完成后弹出
        logout(logoutRemote: false);
      }

      userId.value = userInfoRes.userinfo.id;
      userName.value = userInfoRes.userinfo.name;
      nickName.value = userInfoRes.userinfo.realname ?? "";
      if (userInfoRes.useravatar != null) {
        avatarUrlSet.value = userInfoRes.useravatar!;
      }
    } catch (err, stack) {
      if (kDebugMode) {
        printError(info: "Cannot update profile of current user: $err");
        stack.printError();
      }
    }
  }

  String? getAvatar(int size) {
    if (avatarUrlSet.isEmpty) {
      return null;
    }

    for (var imgSize in avatarUrlSet.keys) {
      if (size < imgSize) {
        return avatarUrlSet[size];
      }
    }

    return avatarUrlSet.values.last;
  }

  /// 从本地存储读取
  void loadFromStorage() {
    try {
      final storage = GetStorage();
      var userInfoJson = storage.read<String>("userInfo");
      if (userInfoJson == null) return;

      var userInfoObject = jsonDecode(userInfoJson);
      if (userInfoObject == null) return;

      var userInfo = UserInfo.fromJson(userInfoObject);

      _ignoreSave = true;
      userId.value = userInfo.userId;
      userName.value = userInfo.userName;
      nickName.value = userInfo.nickName ?? "";
      avatarUrlSet.value = userInfo.avatarUrlSet ?? {};
      _ignoreSave = false;

      var savedLoginRequestToken = storage.read<String>("loginRequestToken");
      if (savedLoginRequestToken != null) {
        _ignoreSave = true;
        loginRequestToken.value = savedLoginRequestToken;
        _ignoreSave = false;
      }
    } catch (ex) {
      if (kDebugMode) {
        print(ex);
      }
    } finally {
      _ignoreSave = false;
    }
  }

  /// 保存到本地存储
  void saveToStorage() {
    if (_ignoreSave) return;

    final storage = GetStorage();

    var userInfo = UserInfo(
      userId: userId.value,
      userName: userName.value,
      nickName: nickName.isNotEmpty ? nickName.value : null,
      avatarUrlSet: avatarUrlSet.isNotEmpty ? avatarUrlSet : null,
    );

    var userInfoJson = jsonEncode(userInfo.toJson());

    storage.write("userInfo", userInfoJson);

    if (loginRequestToken.isNotEmpty) {
      storage.write("loginRequestToken", loginRequestToken.value);
    } else {
      storage.remove("loginRequestToken");
    }
  }

  /// 开始登录流程
  /// 从服务器获取loginRequestToken
  Future<void> startAuthFlow() async {
    authProcessing.value = true;

    try {
      var startAuthRes = await MWApiUser.startAuth();

      var startAuthInfo = startAuthRes.data;
      loginRequestToken.value = startAuthInfo.loginRequestKey;

      await openUrl(startAuthInfo.loginUrl, inApp: true);
    } catch (err, stack) {
      authProcessing.value = false;
      loginRequestToken.value = "";

      alert(Get.overlayContext!, ErrorUtils.getErrorMessage(err), title: "错误");
      if (kDebugMode) {
        print("Exception in startAuthFlow: $err");
        stack.printError();
      }
    }
  }

  // 尝试通过登录请求Token完成登录
  Future<void> attemptFinishAuth() async {
    if (loginRequestToken.isEmpty) {
      authProcessing.value = false;
      return;
    }

    MWResponse<MugenAppAttemptAuthInfo> attemptAuthRes;

    try {
      attemptAuthRes = await MWApiUser.attemptAuth(loginRequestToken.value);
    } catch (err, stack) {
      authProcessing.value = false;
      alert(Get.overlayContext!, ErrorUtils.getErrorMessage(err), title: "错误");
      if (kDebugMode) {
        print("Exception in startAuthFlow: $err");
        stack.printError();
      }
      return;
    }

    var attemptAuthInfo = attemptAuthRes.data;
    if (attemptAuthInfo.status == "pending") {
      authProcessing.value = false;
      loginRequestToken.value = "";

      alert(Get.overlayContext!, "已取消登录", title: "提示");

      return;
    } else if (attemptAuthInfo.status == "success") {
      loginRequestToken.value = "";

      userId.value = attemptAuthInfo.userid!;
      userName.value = attemptAuthInfo.username!;

      await updateProfile();

      authProcessing.value = false;
      saveToStorage();
    }
  }

  Future<void> logout({bool logoutRemote = true}) async {
    if (logoutRemote) {
      // 登出网站
      authProcessing.value = true;

      try {
        await MWApiUser.logout();
      } catch (err, stack) {
        authProcessing.value = false;
        alert(Get.overlayContext!, ErrorUtils.getErrorMessage(err),
            title: "错误");
        if (kDebugMode) {
          print("Exception in logout: $err");
          stack.printError();
        }
      }
    }

    // 清除Cookie
    await BaseApi.clearCookie();

    // 清除所有用户信息
    userId.value = 0;
    userName.value = "";
    nickName.value = "";
    avatarUrlSet.value = {};

    authProcessing.value = false;

    saveToStorage();
  }
}