package com.bohuikeji.frame.module.admin.base;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bohuikeji.frame.module.admin.annotation.TableNewField;
import com.bohuikeji.frame.module.admin.annotation.TableShowField;
import com.bohuikeji.frame.module.admin.entity.sys.SysLog;
import com.bohuikeji.frame.module.admin.entity.sys.SysMenu;
import com.bohuikeji.frame.module.admin.entity.sys.SysUser;
import com.bohuikeji.frame.module.admin.exception.WebVerifiedException;
import com.bohuikeji.frame.module.admin.service.ITFranchiseeInformationService;
import com.bohuikeji.frame.module.admin.utils.NumberUtils;
import com.bohuikeji.frame.module.admin.utils.ReflectUtil;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.StringJoiner;

/**
 * controller父类
 * @author 10552
 */
@Slf4j
public class ControllerBase extends SuperBase {
    @Autowired
    protected HttpSession session;
    @Autowired
    ITFranchiseeInformationService franchiseeInformationService;

    /**
     * 创建空白实体
     *
     * @param model
     * @return
     */
    protected EntityBase crateEntityByName(String model) {
        EntityBase entity = null;
        try {
            Class c = Class.forName(model);
            entity = (EntityBase) c.newInstance();
        } catch (ClassNotFoundException e) {
            log.error("创建Entity失败，无法找到实体类：[{}]", model, e);
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        if (entity == null) {
            log.error("创建Entity失败,未知错误，model：[{}]", model);
        }
        return entity;
    }

    /**
     * 使用map参数创建实体
     *
     * @return
     */
    protected <T extends EntityBase<T>> T crateEntityByMap(Map<String, String> params) {
        return setEntityByMap(crateActiveEntity(),params);
    }
    /**
     * 根据参数创建实体
     * @param entity
     * @param params
     * @return
     */
    protected <T extends EntityBase<T>> T setEntityByMap(T entity,Map<String, String> params){
        Class clss = entity.getClass();
        Field field = null;
        String value="";
        /**
         * 是否编辑操作
         */
        boolean isEdit=false;
        /**
         * 如果为修改则替换空实体为数据实体
         */
        String id=params.get(entity.forIdField().getName());
        if(StringUtils.isNotBlank(id)){
            isEdit=true;
            entity=entity.selectById(id);
        }
        /**
         * 处理非法参数
         */
        for (Map.Entry<String, String> entry : params.entrySet()) {
            log.info("参数：[{}]=[{}]",entry.getKey(),entry.getValue());
            if (StringUtils.isBigDecimal(entry.getKey())){
                log.warn("剔除异常的客户端参数，key:[{}] value:[{}]",entry.getKey(),entry.getValue());
                continue;
            }
            try {
                field = clss.getDeclaredField(entry.getKey());
                field.setAccessible(true);
            } catch (NoSuchFieldException e) {
                log.warn("未找到实体[{}]的属性：[{}]，跳过该属性执行", clss.getName(), entry.getKey());
                continue;
            }
            /**
             * 绑定参数到实体
             */
            TableNewField tableNewField = field.getAnnotation(TableNewField.class);
            /**
             * 未指定新增，跳过
             */
            if(tableNewField==null){
                continue;
            }
            /**
             * 必填判断
             */
            /*if(tableNewField.required()){
                if(StringUtils.isBlank(entry.getValue())){
                    throw new WebVerifiedException(field.getAnnotation(TableShowField.class).value()+"不能为空!");
                }
            }
            if(isEdit){
                ReflectUtil.setValue(entity,field,StringUtils.strtoPojo(entry.getValue(), field.getType()));
                continue;
            }*/
            /**
             * 判断需要自动填充的字段
             */
            value=tableNewField.value();
            switch (tableNewField.way()) {
                case DEFAULT:
                    if (StringUtils.isBlank(entry.getValue())){
                        entry.setValue(value);
                    }break;
                case NUM_UTIL:
                    entry.setValue(NumberUtils.get(tableNewField.pix()));break;
                case AUTO_ADD:
                    value=("".equals(value)?"public_generator":value);
                    long result=(long)entity.sql().selectObj("select auto_value from sys_auto_num where auto_key={0}",value)+1;
                    entity.sql().update("update sys_auto_num set auto_value={0} where auto_key={1}",result,value);
                    /*if(StringUtils.isBlank(entry.getValue())){
                        entry.setValue(tableNewField.pix()+result);
                    }*/
                    entry.setValue(tableNewField.pix()+result);break;
                case AUTO_KEY:
                    String value2=(String)entity.sql().selectObj("select config_name from sys_config where config_key={0}",tableNewField.value());
                    entry.setValue(value2);break;
                case TIMESTAMP:
                    entry.setValue(tableNewField.pix()+System.currentTimeMillis());break;
                case DATETIME:
                    entry.setValue(LocalDateTime.now().format(StringUtils.dataTimeFormat));break;
                case SESSION_USER:
                    entry.setValue(((SysUser)session.getAttribute("loginUser")).getUserId().toString());break;
                case SESSION_FRAN:
                    entry.setValue(((SysUser)session.getAttribute("loginUser")).getFranId().toString());break;
                default:
                    log.error("创建表单组件错误，无法识别TableNewField.way()类型。参数：[{}]",tableNewField.way());
            }
            if (tableNewField.required()){
                if(StringUtils.isBlank(entry.getValue())){
                    throw new WebVerifiedException(field.getAnnotation(TableShowField.class).value()+"不能为空！");

                }
            }
            /**
             * 更新字段
             */
            ReflectUtil.setValue(entity,field,StringUtils.strtoPojo(entry.getValue(), field.getType()));
        }
        return entity;
    }

    /**
     * 获取当前激活的菜单实体
     * @return
     */
    protected <T extends EntityBase> T crateActiveEntity(){
        return (T)crateEntityByName(((SysMenu)session.getAttribute("activeMenu")).getModel());
    }

    /**
     * 后去当前菜单激活实体的指定字段
     * @param fieldName
     * @return
     */
    protected Field crateField(EntityBase entity,String fieldName){
        if (entity==null){
            entity=crateActiveEntity();
        }
        try {
            Field field = entity.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (NoSuchFieldException e) {
            log.error("创建Field失败，无法找到指定字段，位于[{}.{}]",entity.getClass(),fieldName,e);
            throw new RuntimeException(e);
        }
    }
    /**
     * 获取当前session中登陆的用户
     * @return
     */
    protected SysUser getLoginUser(){
        return (SysUser)session.getAttribute("loginUser");
    }

    /**
     * 获取已初始化的日志对象
     * @return
     */
    protected SysLog getLog(HttpServletRequest request){
        SysLog sysLog=(SysLog) request.getAttribute("sys_log");
        if(sysLog==null){
            log.error("【日志服务异常】，获取初始化日志对象失败，执行方法未配置@InitLog注解，抛出异常。地址：[{}]",request.getRequestURI());
            throw new WebVerifiedException("日志初始化异常！");
        }
        return sysLog;
    }

    /**
     * 获取用于判断当前用户所属加盟商的查询QueryWrapper
     * 【注】:使用此方式的数据库实体必须必须含有数据表字段[fran_id(加盟商Id)]，否则报错
     * @return
     */
    protected <T> QueryWrapper<T> getFranQueryWrapper(){
        SysUser user=getLoginUser();
        if (user.getRoleId()==1){
            return new QueryWrapper();
        }
        if (user.getRoleId()==19){
            return new QueryWrapper();
        }
        return new QueryWrapper<T>().in("fran_id", franchiseeInformationService.queryLow(user.getFranId()));
    }

    /**
     * 获取加盟商外键表的sql,用于需要根据加盟商查询数据，但是表字段没有fran_id，需要通过中间表关联查询的情况
     * 调用者需要将该方法返回值设置到 QueryWrapper.inSql条件中
     * @param table 中间表名
     * @param column 匹配字段
     * @return 平台返回null，调用者判断
     */
    protected String getFranSqlByKey(String table,String column){
        SysUser user=getLoginUser();
        if (user.getRoleId()==1){
            return null;
        }
        StringJoiner joiner=new StringJoiner(",");
        for (Object id:franchiseeInformationService.queryLow(user.getFranId())) {
            joiner.add(id.toString());
        }
        return "select "+column+" from "+table+" where fran_id in("+joiner+")";
    }

}
