/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable no-prototype-builtins */
import { App, Pipe, PipeTransform, TransformOptions } from "@midwayjs/core";
import { IMidwayKoaApplication } from "@midwayjs/koa";
import { ComoNestUtils } from "como-nestjs-utils";
// eslint-disable-next-line node/no-extraneous-import
import { ComoRules, ComoValidateRules,ComoObjectType,ComoTsValidate } from "como-ts-utils";
import { ComoValidatorRuleType, ComoValidatorTimingType, GlobalOjectType } from "../interface";

//定义值验证规则时机
export enum QuickRuleOccasion {
    //必须验证
    required = 1,
    //存在就验证
    existisRequired,
    //值不为空的时间验证
    notEmptyRequired
}
/**
 * 自定义数据验证器
 */
@Pipe()
export class BaseValidatePipe<T extends object,R extends object> implements PipeTransform<T,R> {

    @App()
    _app:IMidwayKoaApplication

    //是否过滤
    protected _NotXssFilterKeys:string[] = [];

    /**
     * 基类数据验证器
     * @param value
     * @param transformOptions
     */
    transform(value: T, transformOptions: TransformOptions<unknown>):R{
        const rules = this.Validate(transformOptions.methodName);
        const tmpValue:GlobalOjectType = {};
        for(const key in value) {
            if(this._NotXssFilterKeys.includes(key)) {
                tmpValue[key] = value[key];
            } else {
                tmpValue[key] = this.XssFilter(value[key]);
            }
        }
        const validatorRules = this.GetQuickRules(rules,tmpValue);
        return ComoTsValidate(validatorRules,tmpValue) as R;
    }
    /**
     * xss过滤
     * @param value 
     */
    private XssFilter(value:any) {
        if(typeof value !== 'string') return value;
        return ComoNestUtils.Ins.HtmlEscape(value);
    }

    /**
     * 按方法级别进行验证
     * @param methodName
     */
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    protected Validate(methodName:string):ComoValidatorRuleType {
        const ValidatorFn = `${methodName}Validate`;
        if(!this[ValidatorFn] || (this[ValidatorFn] instanceof Function) === false) {
            const tmps:ComoValidatorRuleType = {};
            for(let key in this) {
                const item = this[key];
                if(item['key'] && item['rule']) {
                    tmps[item['key']] = item['rule'] as unknown as ComoValidatorTimingType | ComoRules;
                }
            }
            return tmps;
        }
        return (this[ValidatorFn] as Function).call(this);
    }
    /**
     * 数据验证
     * @param rules
     * @param data
     * @returns
     */
    private GetQuickRules<T extends object>(rules:ComoValidatorRuleType,data:T):ComoValidateRules {
        const result:ComoValidateRules = {};
        for(const key in rules) {
            const item = rules[key];
            if((item as ComoValidatorTimingType).validaRule) {
                if((item as ComoValidatorTimingType).validaTiming === QuickRuleOccasion.required) {
                    result[key] = (item as ComoValidatorTimingType).validaRule;
                } else if((item as ComoValidatorTimingType).validaTiming === QuickRuleOccasion.existisRequired && data.hasOwnProperty(key)) {
                    result[key] = (item as ComoValidatorTimingType).validaRule;
                } else if((item as ComoValidatorTimingType).validaTiming === QuickRuleOccasion.notEmptyRequired && data.hasOwnProperty(key) && data[key]) {
                    result[key] = (item as ComoValidatorTimingType).validaRule;
                }
            } else {
                result[key] = item as ComoRules;
            }
        }
        return result;
    }
    /**
     * 转换存在验证器
     * @param data
     */
    protected ExistisTransform(data:ComoObjectType) {
        const result:{
            [field:string]:ComoValidatorTimingType
        } = {};
        for(const key in data) {
            result[key] = {
                validaRule:data[key],
                validaTiming:QuickRuleOccasion.existisRequired
            } as ComoValidatorTimingType;
        }
        return result;
    }
}