import {
	app,
	$app
} from '../../../../app/weapps-api';
import loginByPassword from './methods/loginByPassword';
import loginByWXPhone from './methods/loginByWXPhone';
import {
	parseSmsError
} from './methods/errorHandler';
import loginBySms from './methods/loginBySms';
import loginByOpenId from './methods/loginByOpenId';
import loginByUnionId from './methods/loginByUnionId';
import {
	getLoginConfig
} from '../../../../common/util';
import {
	phoneNumberPattern,
	phoneVerifyInfoKey,
	verifyDelay,
	loginOnly
} from './methods/contants';
import loginSuccessCallBack from './methods/loginSuccessCallBack'

const AUTO_LOGIN_TYPE = ['openid_login', 'unionid_login']
const AUTO_LOGIN_METHOD = {
	'openid_login': loginByOpenId,
	'unionid_login': loginByUnionId
}

function decodePageQuery(query) {
	return Object.keys(query).reduce((decoded, key) => {
		decoded[key] = decodeURIComponent(query[key]);
		return decoded;
	}, {});
}

const BUTTON_CLASSNAME = 'weda-ui weda-button weui-btn weui-btn_primary wd-event-tap';

function setStorage(data) {
	const current = wx.getStorageSync(phoneVerifyInfoKey);
	wx.setStorageSync(phoneVerifyInfoKey, {
		...current,
		...data
	});
}

Component({
	data: {
		params: {},
		initing: true,
		error: null,
		settingData: {
			logo: '',
			agreement: {
				items: [],
				enable: false,
			},
			miniprogram: [],
		},
		pageStyle: '',
		agreement: false,
		wxLoginStatus: '',
		passwordVisible: false,
		enablePassword: false,
		enableMpPhone: false,
		enbaleSms: false,
		disableLoginSubmit: false,
		loginButtonClass: BUTTON_CLASSNAME,
		phoneValidateMessage: '手机号为空',
		phoneNum: '',
		defaultPhoneNumber: '',
		smsVerificationInfo: {
			id: '',
			isUser: false,
		},

		currentLoginType: '',
		currentLoginList: [],
		baseInfoShow: false,
		avatarUrl: '',
		avatarRealUrl: '',
		nickName: '',
    publicPage: []
	},
	methods: {
		async getPhoneCodeNumber(e) {
			const agree = this.checkAgreement();
			if (!agree) {
				return;
			}
			if (e?.detail?.errMsg?.includes('fail') || e?.detail?.errno || !e?.detail?.code) {
				console.warn('获取手机号授权令牌失败:', !e?.detail.code ? {
					errMsg: '可能基础库版本过低'
				} : e.detail);

				$app.showModal({
					cancelColor: '#000000',
					cancelText: '取消',
					confirmColor: '#576B95',
					confirmText: '确认',
					showCancel: true,
					title: '获取手机号授权令牌失败',
					content: `获取手机号授权令牌失败: ${e.detail.errno || e.detail?.errMsg || '可能基础库版本过低'}`,
				});

				return;
			}

			return loginByWXPhone(this, {
				event: e
			});
		},
		async onLoad(options) {
			try {
				const cache = wx.getStorageSync(phoneVerifyInfoKey);
				if (cache.phoneNum) {
					this.setData({
						defaultPhoneNumber: cache.phoneNum,
						phoneNum: cache.phoneNum,
						phoneValidateMessage: ''
					});
				}

				const config = await getLoginConfig().catch(() => {
					return getLoginConfig();
				});
				const query = decodePageQuery(options || {});
				let settingData = {
					logo: app.__internal__.resolveStaticResourceUrl(config.logo) ||
						'https://sso-1303824488.cos.ap-shanghai.myqcloud.com/logo.svg',
          name: config.name,
					agreement: {
						items: [],
						enable: false,
						...config.agreement,
					},
					miniprogram: (config.miniprogram || []).map(v => ({
						...v,
						label: v.label?.replace(/^微信小程序/, '')
          })),
          access: { ...config.access },
				};

				const enableSms = this._getEnableSms(settingData);
				const smsDelay =
					enableSms && !cache.phoneNum ? Math.max(0, Math.ceil(((cache?.smsDelay || 0) - +new Date()) / 1000)) : 0;
				const baseInfoShow = !settingData.access?.disabledCollectUserInfo && query.baseInfoShow === 'true'
				const currentLoginType = query.currentLoginType || settingData.miniprogram.filter(v => !AUTO_LOGIN_TYPE.includes(v.type))?.[0]?.type || settingData.miniprogram[0]?.type;
				const currentLoginList = query.currentLoginType ? [] : settingData.miniprogram.filter(v => v.type !== currentLoginType)

				const {
					avatarUrl,
					nickName
				} = app.auth.currentUser
				const avatarRealUrl = await this.getAvatarUrl(avatarUrl)

				this.setData({
					params: query,
					settingData,
					enablePassword: this._getEnablePassword(settingData),
					enableMpPhone: this._getEnableMpPhone(settingData),
					enableSms,
					smsDelay,
					smsVerificationInfo: cache,
					pageStyle: `${this.data.pageStyle}; background-color: ${config.backgroundColor || '#fff'};`,
					initing: false,
					currentLoginType,
					currentLoginList,
					baseInfoShow,
					avatarRealUrl,
					avatarUrl,
					nickName,
          publicPage: (app.__internal__?.getConfig() || {})?.publicPage || [],
				});

				if (smsDelay > 0) {
					this._intervalSender(smsDelay);
				}

				if (settingData.miniprogram.length === 1 && AUTO_LOGIN_TYPE.includes(currentLoginType) && !baseInfoShow) {
					await this.dealOpenIdOrUnionIdLogin(currentLoginType);
				}
			} catch (e) {
				console.error('获取登录配置失败:', e);
				this.setData({
					initing: false,
					error: {
						message: '获取登录配置失败,' + (e.message || ''),
					},
				});
			}
		},
		togglePasswordVisible() {
			this.setData({
				passwordVisible: !this.data.passwordVisible,
			});
		},
		loginByPassword(e) {
			if (!this.checkAgreement()) {
				return;
			}

			const values = e.detail.value;

			return loginByPassword(this, {
				phone: values?.username?.value,
				sms: values?.password?.value,
			});
		},
		loginBySms(e) {
			if (!this.checkAgreement()) {
				return;
			}

			const values = e.detail.value;

			return loginBySms(this, {
				phoneNum: values?.phoneNum,
				verificationCode: values?.verificationCode,
				verificationInfo: this.data.smsVerificationInfo,
				callback: (err, data) => {
					if (err) {
						const {
							usedCount = 0
						} = wx.getStorageSync(phoneVerifyInfoKey) || {};
						setStorage({
							usedCount: usedCount + 1
						});
					} else {
						setStorage({
							usedCount: 0,
							smsDelay: 0
						});
					}
				},
			});
		},
		showAgreement(e) {
			const index = e.currentTarget?.dataset?.index;
			const agreementContent = this.data.settingData.agreement.items[index]?.value;
			this.setData({
				agreementContent,
				isShowAgreement: !!agreementContent,
			});
		},
		checkAgreement() {
			if (this.data.settingData?.agreement?.enable && !this.data.agreement) {
				app.showToast({
					title: '请阅读勾选协议',
					icon: 'error',
					duartion: 1500,
				});

				return false;
			}
			return true;
		},
		onAgreementChange(e) {
			this.setData({
				agreement: e.detail.value.length > 0,
			});
		},
		onPhoneChange(e) {
			const {
				value
			} = e.detail;
			if (!phoneNumberPattern.test(value)) {
				this.setData({
					phoneValidateMessage: '手机号格式非法',
					phoneNum: value
				});
			} else {
				this.setData({
					phoneValidateMessage: '',
					phoneNum: value
				});
			}
		},
		getCaptcha(e) {
			if (!this.checkAgreement()) {
				return;
			}

			if (this.data.phoneValidateMessage) {
				wx.showToast({
					icon: 'error',
					title: this.data.phoneValidateMessage,
				});
				return;
			}
			if (this.data.smsDelay > 0) {
				return;
			}
			this._intervalSender(verifyDelay);
			const target = loginOnly ? 'USER' : 'ANY';
			const phoneNum = this.data.phoneNum;
			app.cloud
				.getCloudInstance()
				.then((cloudbase) => {
					return cloudbase.authInstance || cloudbase.auth;
				})
				.then((auth) => {
					setStorage({
						phoneNum
					});
					return auth.getVerification({
						target,
						phone_number: `+86 ${phoneNum}`,
					});
				})
				.then((data) => {
					const verifyInfo = {
						id: data.verification_id,
						isUser: data.is_user,
					};
					this.setData({
						smsVerificationInfo: verifyInfo,
					});
					setStorage({
						...verifyInfo,
						usedCount: 0
					});
					wx.showToast({
						title: '验证码已发送',
					});
				})
				.catch((e) => {
					wx.hideLoading()
					clearInterval(this.timerInterval);
					this.setData({
						smsDelay: 0
					});
					setStorage({
						smsDelay: 0
					});
					wx.showModal({
						title: '获取验证码失败',
						content: parseSmsError(e, target, loginOnly),
						showCancel: false,
					});
				});
		},
		_getEnablePassword(settingData) {
			const config = settingData || this.data.settingData;
			return config.miniprogram?.find?.((item) => item.type === 'password')?.enable ?? false;
		},
		_getEnableMpPhone(settingData) {
			const config = settingData || this.data.settingData;
			return !!config.miniprogram.find(function (item) {
				return item.type === 'miniprogram_phone';
			})?.enable;
		},
		_getEnableSms(settingData) {
			const config = settingData || this.data.settingData;
			return !!config.miniprogram.find(function (item) {
				return item.type === 'sms';
			})?.enable;
		},
		_intervalSender(delay) {
			this.setData({
				smsDelay: delay
			});
			const timerInterval = setInterval(() => {
				delay = delay - 1;
				if (delay <= 0) {
					clearInterval(timerInterval);
				}
				this.setData({
					smsDelay: delay
				});
				setStorage({
					smsDelay: +new Date() + delay * 1000
				});
			}, 1000);
			this.timerInterval = timerInterval;
		},
		compareVersion(version1, version2) {
			// 将版本号字符串分割成数组
			const v1 = version1.split('.');
			const v2 = version2.split('.');

			// 获取两个版本号数组的最大长度
			const maxLength = Math.max(v1.length, v2.length);

			// 遍历版本号数组并比较每个部分
			for (let i = 0; i < maxLength; i++) {
				// 如果某个版本号的长度较短，则将其补0
				const num1 = parseInt(v1[i] || 0, 10);
				const num2 = parseInt(v2[i] || 0, 10);

				// 比较当前位置的数字大小
				if (num1 > num2) {
					return 1;
				} else if (num1 < num2) {
					return -1;
				}
			}

			// 如果所有位置的数字都相同，则两个版本号相等
			return 0;
		},
		async getAvatarUrl(avatarUrl) {
			let avatarRealUrl = avatarUrl
			if (avatarUrl.startsWith('cloud://')) {
				const tcb = await app.cloud.getCloudInstance()
				const pic = await tcb.getTempFileURL({
					fileList: [avatarUrl]
				})
				avatarRealUrl = pic?.fileList?.[0]?.tempFileURL || ''
			}

			return avatarRealUrl;
		},
		async dealOpenIdOrUnionIdLogin(type) {
			try {
				const res = await (AUTO_LOGIN_METHOD[type])(this);
				if (res) {
					const {
						avatarUrl,
						nickName
					} = app.auth.currentUser
					const {
						SDKVersion
					} = wx.getSystemInfoSync();
          // 2.21.2以下版本不支持获取用户头像/昵称，暂时跳过
					if (!this.data.settingData?.access?.disabledCollectUserInfo && (!avatarUrl || !nickName) && this.compareVersion(SDKVersion, '2.21.2') >= 0) {
						const avatarRealUrl = await this.getAvatarUrl(avatarUrl)
						this.setData({
							avatarRealUrl,
							avatarUrl,
							nickName,
							baseInfoShow: true
						})
					} else {
						loginSuccessCallBack(this);
					}
				}
			} catch (error) {

			}
		},
		jumpBaseInfoConfig() {
			loginSuccessCallBack(this);
		},
		methodClick(e) {
			const {
				type
			} = e.currentTarget.dataset.item || {};

			const currentLoginType = type || this.data.currentLoginType;

			this.setData({
				currentLoginType,
				currentLoginList: this.data.settingData.miniprogram.filter(v => v.type !== currentLoginType)
			})

			if (AUTO_LOGIN_TYPE.includes(currentLoginType)) {
				if (this.data.disableLoginSubmit) {
					wx.showToast({
						title: '请先阅读并同意协议',
						icon: 'none'
					})
					return;
				};
				this.dealOpenIdOrUnionIdLogin(currentLoginType)
				return;
			}
		},
		onChooseAvatar(e) {
			this.setData({
				avatarUrl: e.detail.avatarUrl,
				avatarRealUrl: '',
			})
		},
		nickNameChange(e) {
			this.setData({
				nickName: e.detail.value
			})
		},
		randomStr(len = 32) {
			const s = [];
			const hexDigits = '0123456789abcdef';
			const dictLen = hexDigits.length;
			for (var i = 0; i < len; i++) {
				const index = Math.floor(Math.random() * dictLen);
				s[i] = hexDigits[index];
			}
			const result = s.join('');
			return result;
		},
		async uploadFile(file) {
			return new Promise(async (resolve) => {
				const uploadPath = 'weda-uploader';
				const fileType = file.split('.')?.slice(-1)?.[0];
				const cloudPath = `${uploadPath}/${this.randomStr()}-${Date.now()}.${fileType}`;
				try {
					const tcb = await app.cloud.getCloudInstance();
					const res = await tcb.uploadFile({
						cloudPath: cloudPath,
						filePath: file,
					});
					if (res.fileID) {
						resolve(res)
					} else {
						throw res
					}
				} catch (e) {
					wx.showModal({
						title: '上传失败，请重试',
						content: e.message,
						showCancel: false,
					});
					resolve({});;
				}
			})
		},
		async baseInfoConfirm() {
			let {
				avatarUrl,
				nickName,
				currentLoginType,
			} = this.data

			wx.showLoading()

			if (avatarUrl && !avatarUrl.startsWith('cloud://')) {
				const res = await this.uploadFile(avatarUrl)
				avatarUrl = res.fileID || ''
			}

			try {
				const tcb = await app.cloud.getCloudInstance();
				await tcb.auth.updateUserBasicInfo({
					avatar_url: avatarUrl,
					nickname: nickName,
					user_id: app.auth.currentUser.userId
				});
				await (AUTO_LOGIN_METHOD[currentLoginType])(this);
				loginSuccessCallBack(this);
			} catch (error) {
				wx.showModal({
					title: '更新用户信息出错',
					content: error.message,
					showCancel: false,
				});
			}

			wx.hideLoading()
		},
    loginCancel() {
      if (this.data.publicPage?.length <= 0) return;

      const toPage = this.data.publicPage[0]
      const toPagePath = toPage.split('/')
      const pageId = toPagePath.length > 1 ? toPagePath[1] : toPagePath[0]
      const packageName = toPagePath.length > 1 ? toPagePath[0] : undefined

      try {
        const path = app.__internal__.generatePageUrl({
          pageId,
          packageName,
        })
        wx.restartMiniProgram({
          path
        })
      } catch (error) {
        app.redirectTo({
          pageId,
          packageName,
        })
      }
    }
	},
	observers: {
		'settingData,agreement': function (settingData, agreement) {
			const disabled = settingData?.agreement?.enable && !agreement;
			if (!!this.data.disableLoginSubmit !== disabled) {
				this.setData({
					disableLoginSubmit: disabled
				});
			}
		},
		disableLoginSubmit: function (disableLoginSubmit) {
			this.setData({
				loginButtonClass: `${BUTTON_CLASSNAME} ${disableLoginSubmit ? 'is-disabled' : ''}`,
			});
		},
	},
});
