import { base64EncodeSync, md5EncryptSync } from "@normalized:N&&&@abner/security/Index&1.0.2";
import { FaceResultRequest, QueryContext, ValidateParam, WakeUpFaceRequest } from "@normalized:N&&&esignfacesdk/src/main/ets/Data/DataModel&1.0.0";
import type { AppSdkLicense, AppSdkLicenseInfo, CheckResult, FaceResultQueryResponse, LocalData, ValidateResponse, WakeUpResponse } from "@normalized:N&&&esignfacesdk/src/main/ets/Data/DataModel&1.0.0";
import util from "@ohos:util";
import cryptoFramework from "@ohos:security.cryptoFramework";
import { InputData, WbCloudFaceVerifySdk, WbFaceError, WbFaceVerifyConfig, WbFaceVerifyResult } from "@normalized:N&&&wbcloudfaceverifysdk/Index&1.2.1";
import { DEBUG } from "@normalized:N&&&esignfacesdk/BuildProfile&1.0.0";
import type { BusinessError } from "@ohos:base";
import router from "@ohos:router";
import "@normalized:N&&&esignfacesdk/src/main/ets/pages/WebView&1.0.0";
import { Esign } from "@normalized:N&&&esignfacesdk/src/main/ets/Data/Esign&1.0.0";
import type common from "@ohos:app.ability.common";
export class EsignSDK {
    private static instance: EsignSDK | null = null;
    private constructor() {
    }
    //单例
    public static getInstance(): EsignSDK {
        if (!EsignSDK.instance) {
            EsignSDK.instance = new EsignSDK();
        }
        return EsignSDK.instance;
    }
    //请求地址域名
    private mUrlDomain: string = '';
    //license列表
    private mAppSdkLicenseList: Array<AppSdkLicense> = new Array();
    //开放平台申请的licenseKey
    private licenseKey: string = '';
    //开放平台申请的license
    private license: string = '';
    //刷脸请求Code
    private faceAuthCode: string = '';
    //初始化SDK
    public async initSDK(licenseKey: string, license: string, callBack: InitCallback) {
        //初始化回调内容
        let initResponse: InitResponse = new InitResponse();
        //校验key和licenses是否为空
        if (licenseKey == null || license == null) {
            initResponse.msg = 'key或lincese不能为空';
            callBack(initResponse);
            return;
        }
        //替换前缀
        if (licenseKey.startsWith("t_")) {
            licenseKey = licenseKey.replace("t_", "");
        }
        else if (licenseKey.startsWith("s_")) {
            licenseKey = licenseKey.replace("s_", "");
        }
        else if (licenseKey.startsWith("p_")) {
            licenseKey = licenseKey.replace("p_", "");
        }
        //替换前缀
        if (license.startsWith("t_")) {
            license = license.replace("t_", "");
        }
        else if (license.startsWith("s_")) {
            license = license.replace("s_", "");
        }
        else if (license.startsWith("p_")) {
            license = license.replace("p_", "");
        }
        //赋值licenseKey和license
        this.licenseKey = licenseKey;
        this.license = license;
        //解密license内容
        let localDataStr = await this.decrypt(licenseKey, license);
        if (localDataStr == null) {
            initResponse.msg = 'key或lincese异常';
            callBack(initResponse);
            return;
        }
        //json字符串转成对象
        const localData: LocalData = JSON.parse(localDataStr);
        if (localData == null || localData.appDate == null) {
            initResponse.msg = 'key或lincese异常';
            callBack(initResponse);
            return;
        }
        //校验包名和key
        let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
        if (licenseKey != localData?.appDate?.feature || localData?.appDate
            ?.bundleId !== context.abilityInfo.bundleName) {
            initResponse.success = false;
            initResponse.msg = 'key或lincese异常';
            callBack(initResponse);
            return;
        }
        //校验接口 封装signature
        const now: Date = new Date();
        let pituLicense: string = localData?.pituLicense;
        let bundleId: string = localData?.appDate?.bundleId;
        let platform: string = localData?.appDate?.platform;
        let deviceId = "deviceId";
        let time = now.getTime();
        let signature = md5EncryptSync(base64EncodeSync(pituLicense + bundleId + platform + time + deviceId));
        //封装校验接口请求数据
        let param: ValidateParam = new ValidateParam();
        param.pituLicense = pituLicense;
        param.bundleId = bundleId;
        param.platform = platform;
        param.timestamp = time + '';
        param.deviceId = deviceId;
        param.signature = signature;
        param.sdkVersion = '1.0.0';
        let esign = new Esign();
        //url校验
        if (localData.appDate.url == null) {
            initResponse.msg = '解析校验地址为空';
            callBack(initResponse);
            return;
        }
        //调用接口校验
        let validateResponse = await esign.validateData(localData.appDate.url, param).catch((err: BusinessError) => {
            console.error(`Response err: Code is ${err.code}, message is ${JSON.stringify(err)}`);
            return '';
        });
        //内容为空
        if (validateResponse == null) {
            initResponse.msg = '数据校验失败';
            callBack(initResponse);
            return;
        }
        const response: ValidateResponse = JSON.parse(validateResponse.toString() || '');
        //解密返回值
        //内容为空
        if (response.data == null) {
            initResponse.msg = '数据校验失败';
            callBack(initResponse);
            return;
        }
        //解密校验返回数据
        let checkResultResponse = await this.decrypt(licenseKey, response.data);
        if (checkResultResponse == null) {
            initResponse.msg = '数据校验失败';
            callBack(initResponse);
            return;
        }
        //校验返回数据转成对象
        const checkResult: CheckResult = JSON.parse(checkResultResponse.toString() || '');
        if (checkResult == null) {
            initResponse.msg = '数据校验失败';
            callBack(initResponse);
            return;
        }
        if (checkResult.appSdkLicenseInfo == null) {
            initResponse.msg = '数据校验失败';
            callBack(initResponse);
            return;
        }
        else {
            //appSdkLicenseInfo不为空  解析appSdkLicenseInfo列表
            let appSdkLicenseInfo: AppSdkLicenseInfo = JSON.parse(checkResult.appSdkLicenseInfo.toString() || '');
            if (appSdkLicenseInfo != null) {
                //初始化成功
                if (appSdkLicenseInfo.urlDomain && appSdkLicenseInfo.inlayAppSdkLicenseList) {
                    this.mUrlDomain = appSdkLicenseInfo.urlDomain;
                    this.mAppSdkLicenseList = appSdkLicenseInfo.inlayAppSdkLicenseList;
                    initResponse.success = true;
                    callBack(initResponse);
                    return;
                }
                else {
                    //初始化失败
                    initResponse.msg = '服务端数据异常';
                    callBack(initResponse);
                    return;
                }
            }
            else {
                initResponse.msg = '数据校验失败';
                callBack(initResponse);
                return;
            }
        }
    }
    //刷脸核身
    async verity(faceAuthCode: string, callBack: VerityCallback) {
        let faceResultResponse: FaceResultResponse = new FaceResultResponse();
        //校验SDK是否初始化
        if (this.isEmpty(this.licenseKey) || this.isEmpty(this.license) || this.mAppSdkLicenseList == null ||
            this.mAppSdkLicenseList.length == 0 || this.isEmpty(this.mUrlDomain)) {
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = '请先调用initSDK方法初始化SDK';
            callBack(faceResultResponse);
            return;
        }
        //校验faceAuthCode
        if (this.isEmpty(faceAuthCode)) {
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = 'faceAuthCode不能为空';
            callBack(faceResultResponse);
            return;
        }
        this.faceAuthCode = faceAuthCode;
        //封装请求唤起刷脸接口的参数
        let param: WakeUpFaceRequest = new WakeUpFaceRequest();
        param.faceAuthCode = faceAuthCode;
        param.faceAuthMode = 'APP_FACE_SDK';
        let query: QueryContext = new QueryContext();
        query.esignAppSdkVersion = 'esign-1.0.0';
        query.clientType = 'Android';
        param.queryContext = query;
        let esign = new Esign();
        //调用接口返回唤起刷脸参数
        let verityResponse = await esign.verity(this.mUrlDomain + '/account-webserver/v2/identity/auth/web/faceauth/wakeup-face', param)
            .catch((err: BusinessError) => {
            console.error(`Response err: Code is ${err.code}, message is ${JSON.stringify(err)}`);
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = '接口请求失败';
            callBack(faceResultResponse);
            return '';
        });
        //接口异常场景
        if (verityResponse == null) {
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = '接口请求失败';
            callBack(faceResultResponse);
            return;
        }
        const response: WakeUpResponse = JSON.parse(verityResponse.toString() || '');
        if (response == null) {
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = '接口请求失败';
            callBack(faceResultResponse);
            return;
        }
        if (response.success == false || response.data == null) {
            faceResultResponse.passed = false;
            faceResultResponse.completed = false;
            faceResultResponse.msg = response.message;
            callBack(faceResultResponse);
            return;
        }
        //返回刷脸降级场景
        if ("BYTEDANCE" === response.data.faceAuthMode || "TENCENT" === response.data.faceAuthMode) {
            //判断跳转H5地址
            if (response.data.identityUrl != null && response.data.config.resultH5Url != null) {
                //跳转打开H5
                this.navigateToWebView(response.data.identityUrl, response.data.config.resultH5Url, (result: FaceResultResponse) => {
                    //H5流程结束进行结果查询
                    this.queryFaceResult(faceAuthCode, new WbFaceVerifyResult(), new WbFaceError(), callBack);
                });
            }
        }
        else {
            //腾讯云SDK刷脸场景
            const currentAppSDK = this.mAppSdkLicenseList.find((appSDkLicense: AppSdkLicense) => appSDkLicense.sdkChannel ===
                response.data.faceAuthMode);
            if (currentAppSDK) {
                //封装唤起刷脸数据
                let inputData: InputData = new InputData(response.data.faceContext.orderNo, currentAppSDK.wbAppId, '1.0.0', response.data.faceContext.nonce, response.data.faceContext.userId, response.data.ticket, currentAppSDK.harmonyOsLicense, response.data.faceContext.faceId);
                console.error(JSON.stringify(inputData));
                //设置页面的设置
                let wbFaceVerifyConfig: WbFaceVerifyConfig = new WbFaceVerifyConfig(inputData);
                //用户设置
                //是否打开sdk日志开关
                // fixme【注意】上线请勿开启
                wbFaceVerifyConfig.isEnableLog = DEBUG;
                //根据版本调用不同的api
                if ('FACE_TECENT_SDK_BASIC' === response.data.faceAuthMode) {
                    WbCloudFaceVerifySdk.getInstance().initSdk(getContext(), wbFaceVerifyConfig, {
                        onLoginSuccess: () => {
                            console.error(`onLoginSuccess:`);
                            WbCloudFaceVerifySdk.getInstance().startWbFaceVerifySdk(getContext(), {
                                onFinish: (_result: WbFaceVerifyResult) => {
                                    console.info(`WbCloudFaceVerifySdk onFinish`);
                                    //刷脸成功进行结果查询
                                    this.queryFaceResult(this.faceAuthCode, _result, null, callBack);
                                    //todo 处理刷脸结果
                                    //处理完后释放sdk
                                    // fixme【特别注意】请在拿到sdk结果后对sdk进行释放，不要在页面结束时释放，避免未能获取刷脸回调结果的情况
                                    WbCloudFaceVerifySdk.getInstance().release();
                                }
                            });
                        },
                        onLoginFail: (error?: WbFaceError) => {
                            console.log('11:' + JSON.stringify(error));
                            console.error(`onLoginFailed:JSON.stringify(error)`);
                            //刷脸失败进行结果查询
                            this.queryFaceResult(this.faceAuthCode, null, error, callBack);
                            //【特别注意】请在拿到sdk结果后对sdk进行释放，不要在页面结束时释放，避免未能获取刷脸回调结果的情况
                            WbCloudFaceVerifySdk.getInstance().release();
                        }
                    });
                }
                else if ('FACE_TECENT_SDK_PLUS' === response.data.faceAuthMode) {
                    WbCloudFaceVerifySdk.getInstance().initAdvSdk(getContext(), wbFaceVerifyConfig, {
                        onLoginSuccess: () => {
                            console.error(`onLoginSuccess:`);
                            WbCloudFaceVerifySdk.getInstance().startWbFaceVerifySdk(getContext(), {
                                onFinish: (_result: WbFaceVerifyResult) => {
                                    console.info(`WbCloudFaceVerifySdk onFinish`);
                                    //刷脸成功进行结果查询
                                    this.queryFaceResult(this.faceAuthCode, _result, null, callBack);
                                    //todo 处理刷脸结果
                                    //处理完后释放sdk
                                    // fixme【特别注意】请在拿到sdk结果后对sdk进行释放，不要在页面结束时释放，避免未能获取刷脸回调结果的情况
                                    WbCloudFaceVerifySdk.getInstance().release();
                                }
                            });
                        },
                        onLoginFail: (error?: WbFaceError) => {
                            console.error(`onLoginFailed:JSON.stringify(error)`);
                            //刷脸失败进行结果查询
                            this.queryFaceResult(this.faceAuthCode, null, error, callBack);
                            //展示刷脸结果页
                            //【特别注意】请在拿到sdk结果后对sdk进行释放，不要在页面结束时释放，避免未能获取刷脸回调结果的情况
                            WbCloudFaceVerifySdk.getInstance().release();
                        }
                    });
                }
            }
            else {
                faceResultResponse.passed = false;
                faceResultResponse.completed = false;
                faceResultResponse.msg = '接口请求失败';
                callBack(faceResultResponse);
            }
        }
    }
    private async decrypt(sKey: string, ciphertext_base64: string): Promise<string> {
        // 1. 处理密钥生成
        const encoder = new util.TextEncoder();
        const keyBytes = encoder.encodeInto(sKey);
        const keyData = new Uint8Array(16);
        keyData.fill(0);
        const copyLength = Math.min(keyBytes.length, 16);
        for (let i = 0; i < copyLength; i++) {
            keyData[i] = keyBytes[i];
        }
        // 2. 创建AES密钥
        const symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES128');
        const keyBlob: cryptoFramework.DataBlob = { data: keyData };
        const symKey = await symKeyGenerator.convertKey(keyBlob);
        // 3. 创建并初始化Cipher
        const cipher = cryptoFramework.createCipher('AES128|ECB|PKCS7');
        await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null);
        // 4. Base64解码
        const decodedData = new util.Base64Helper().decodeSync(ciphertext_base64);
        // 5. 执行解密
        const inputBlob: cryptoFramework.DataBlob = { data: decodedData };
        const outputBlob = await cipher.doFinal(inputBlob);
        // 6. 转换为UTF-8字符串
        const decoder = new util.TextDecoder('utf-8');
        return decoder.decode(outputBlob.data);
    }
    //查询刷脸结果
    async queryFaceResult(faceAuthCode: string, wbFaceVerifyResult: WbFaceVerifyResult, error: WbFaceError, callback: FaceH5VerifyCallback) {
        let map: Map<string, string> = new Map();
        if (wbFaceVerifyResult != null) {
            map["originalReturnData"] = JSON.stringify(wbFaceVerifyResult);
        }
        if (error != null) {
            map["originalReturnData"] = JSON.stringify(error);
        }
        let param: FaceResultRequest = new FaceResultRequest();
        param.faceAuthCode = faceAuthCode;
        param.faceAuthMode = 'APP_FACE_SDK';
        param.extendedMap = map;
        let esign = new Esign();
        let faceResultResponse = await esign.queryFaceResult(this.mUrlDomain + '/account-webserver/v2/identity/auth/web/faceauth/face-result', param).catch((err: BusinessError) => {
            console.error(`Response err: Code is ${err.code}, message is ${JSON.stringify(err)}`);
            return '';
        });
        if (faceResultResponse == null) {
        }
        //刷脸结果回调到调用方
        const queryResponse: FaceResultQueryResponse = JSON.parse(faceResultResponse.toString() || '');
        callback(queryResponse.data);
    }
    /**
     * 判断值是否为空（支持字符串、对象、数组、null/undefined）
     * @param value 待判断的值
     * @returns 是否为空
     */
    isEmpty(str: string): boolean {
        if (str === null || str.length == 0 || str === 'undefined') {
            return true;
        }
        return false;
    }
    //跳转到WebView
    navigateToWebView(url: string, resultH5: string, callBack: FaceH5VerifyCallback) {
        router.pushNamedRoute({
            name: 'WebView',
            params: {
                'url': url,
                'resultH5Url': resultH5,
                'callBack': callBack
            },
        });
    }
}
export class InitResponse {
    success: boolean = false;
    code: string = '10000001';
    msg: string = '';
}
export class FaceResultResponse {
    completed: boolean = false;
    passed: boolean = false;
    errCode: string = '10000001';
    msg: string = '';
    extendedMap: Map<string, string> = new Map();
}
type InitCallback = (result: InitResponse) => void;
type VerityCallback = (result: FaceResultResponse) => void;
export type FaceH5VerifyCallback = (result: FaceResultResponse) => void;
