package com.sptg.gateway.controller.permissions;

import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.plugins.Page;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.CommonConstant;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.SysLogConstant;
import com.sptg.common.core.util.WebUtils;
import com.sptg.common.security.annotation.Security;
import com.sptg.common.security.enums.DataFormatEnum;
import com.sptg.common.security.service.SecurityServiceInterface;
import com.sptg.permissions.api.constant.ConfTokenName;
import com.sptg.permissions.api.constant.PermissionsSecurityToken;
import com.sptg.permissions.api.dto.AccountDto;
import com.sptg.permissions.api.entity.*;
import com.sptg.permissions.api.feigns.*;
import com.sptg.statistics.api.constant.SysLogMenuConstant;
import com.sptg.statistics.api.entity.SysOperationLog;
import com.sptg.statistics.api.feigns.SysOperationLogFeign;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * title: AccountController
 * package: com.sptg.gateway.controller.permissions
 * description: 账户-控制器
 *
 *
 *
 */
@RestController
@RequestMapping(value = "/permissions/account")
@RequiredArgsConstructor
public class AccountController {

    private final ConfFeign confFeign;
    private final SecurityServiceInterface<Account> securityServiceInterface;
    private final OrgFeign orgFeign;
    private final AccountFeign accountFeign;
    private final RoleFeign roleFeign;
    private final SysOperationLogFeign sysOperationLogFeign;
    private final MenuFeign menuFeign;

    /* --------------------------------------------------- 控制器 --------------------------------------------------- */

    @Security(format = DataFormatEnum.JSON)
    @PostMapping(value = "/setup")
    public ResultBean<Boolean> setup(AccountDto dto){
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        Assert.notNull(dto,"参数异常");
        Assert.hasText(dto.getUserName(),"请输入用户姓名");
        Assert.hasText(dto.getLoginPwd(),"请输入密码");
        if (StringUtils.isEmpty(dto.getUserPortraitUri())){
            dto.setUserPortraitUri(null);
        }else {
            onLineUser.setUserPortraitUri(dto.getUserPortraitUri());
        }
        if (CommonConstant.HIDE.equals(dto.getLoginPwd())){
            dto.setLoginPwd(null);
        }
        dto.setId(onLineUser.getId());
        dto.setLoginName(onLineUser.getLoginName());
        ResultBean<Boolean> result = this.accountFeign.updateEnitiy(dto);
        if (result.getCode().equals(ResultEnum.SUCCESS.getCode())){
            onLineUser.setUserMobile(dto.getUserMobile());
            onLineUser.setUserName(dto.getUserName());
            this.securityServiceInterface.updateAccount(onLineUser);
        }
        return result;
    }

    /**
     * 功能描述: 根据条件分页查询账号列表
     * @param dto 查询条件
     * @param pageBean 分页条件
     * @return ResultBean<Page>
     *
     *
     */
    @GetMapping(value = "/pagingQuery")
    @Security(token = PermissionsSecurityToken.ACCOUNT_MANAGE,format = DataFormatEnum.JSON)
    public ResultBean<Page> pagingQuery(AccountDto dto,PageBean<Account,AccountDto> pageBean){
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
//        dto.setOrgPosition(onLineUser.getOrgPosition());
        dto.setOnLineUser(onLineUser);
        //  判断是否选中机构
        if (null != dto.getSelectedId()){
            //有选中
            Organization selectedOrg = this.orgFeign.getOrgById(dto.getSelectedId());
            if (null != selectedOrg){
                if (selectedOrg.getOrgType() == OperationConstant.THREE){
                    //选中物业类型
                    dto.setEstatePosition(selectedOrg.getPosition());
                }else{
                    //选中机构类型
                    dto.setOrgPosition(selectedOrg.getPosition());
                }
            }
        }else {
            //无选中
            Organization userOrg = this.orgFeign.getOrgById(onLineUser.getOrgId());
            if (userOrg.getOrgType() == OperationConstant.THREE){
                //物业账号
                dto.setEstatePosition(userOrg.getPosition());
            }else{
                //机构账号
                dto.setOrgPosition(userOrg.getPosition());
            }
        }

        pageBean.setDto(dto);
        return this.accountFeign.pagingQuery(pageBean);
    }

    /**
     * 功能描述: 根据条件分页查询账号列表
     * @param dto 查询条件
     * @param pageBean 分页条件
     * @return ResultBean<Page>
     *
     *
     */
    @GetMapping(value = "/page")
    @Security(token = PermissionsSecurityToken.ACCOUNT_MANAGE,format = DataFormatEnum.JSON)
    public ResultBean<Page> page(AccountDto dto,PageBean<Account,AccountDto> pageBean){
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
//        dto.setOrgPosition(onLineUser.getOrgPosition());
        dto.setOnLineUser(onLineUser);
        //  判断是否选中机构

        Organization userOrg = this.orgFeign.getOrgById(onLineUser.getOrgId());
        if (userOrg.getOrgType() == OperationConstant.THREE){
            //物业账号
            dto.setEstatePosition(userOrg.getPosition());
        }else{
            //机构账号
            dto.setOrgPosition(userOrg.getPosition());
        }

        pageBean.setDto(dto);
        Page<Account> page = this.accountFeign.page(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS, page);
    }

    /**
     * 功能描述: 获取当前用户的可操作权限树形列表
     * @return ResultBean<Menu>
     *
     *
     */
    @Security(format = DataFormatEnum.JSON)
    @GetMapping(value = "/getMyPermissionsTreeList")
    public ResultBean<Menu> getMyPermissionsTreeList(){
//        Account onLineUser = this.securityServiceInterface.getOnLineUser();
//        return new ResultBean<>(ResultEnum.SUCCESS,onLineUser.getMenuList());
        ResultBean<Menu> menuTreeList = this.menuFeign.getMenuTreeList();
        return menuTreeList;
    }

    /**
     * 功能描述: 获取当前登陆用户机构下的角色列表
     * @return ResultBean<Role>
     *
     *
     */
    @GetMapping(value = "/getMyOrgRoleList")
    @Security(format = DataFormatEnum.JSON)
    public ResultBean<Role> getMyOrgRoleList(){
        //  获取当前用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        //  获取当前登陆账号机构下的角色列表
        List<Role> roleList = this.roleFeign.getListByOrgId(onLineUser.getOrgId());
        return new ResultBean<>(ResultEnum.SUCCESS,roleList);
    }


    /**
     * 功能描述: 创建账号
     * @param dto 账号信息
     * @return ResultBean<Account>
     *
     *
     */
    @PostMapping(value = "/add")
    @Security(token = PermissionsSecurityToken.ACCOUNT_INSERT,format = DataFormatEnum.JSON)
    public ResultBean<Account> add(AccountDto dto){
        //  用户默认头像
        if (StringUtils.isEmpty(dto.getUserPortraitUri())){
            Conf conf = this.confFeign.getEntityByToken(ConfTokenName.DEFAULT_PORTRAIT);
            if (null == conf){
                return new ResultBean<>(ResultEnum.ERROR);
            }
            dto.setUserPortraitUri(conf.getConfValue());
        }
        //  获取当前登陆用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        Organization userOrg = this.orgFeign.getOrgById(onLineUser.getOrgId());
        if (userOrg.getOrgType() == OperationConstant.THREE){
            //物业账号
        }else{
            //机构账号
        }
        dto.setOnLineUser(onLineUser);
        dto.setCreateIp(WebUtils.getIp());
        ResultBean<Account> resultBean=this.accountFeign.addEntity(dto);
        Account account=resultBean.getData();
        if(account!=null){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ADD_EVENT,
                    WebUtils.getIp(),account,onLineUser,account);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 修改账号信息
     * @param dto 账号信息
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/edit")
    @Security(token = PermissionsSecurityToken.ACCOUNT_UPDATE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> edit(AccountDto dto){
        Assert.notNull(dto,"非法参数");
        Assert.notNull(dto.getId(),"账号Id不能为空");
        Account oldObj = this.accountFeign.getById(dto.getId());
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<Boolean> resultBean=this.accountFeign.updateEnitiy(dto);
        if(null!= resultBean.getData() && resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(dto.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }


    /**
     * 功能描述: 重置账号密码
     * @param dto 账号信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/resetPassword")
    @Security(token = PermissionsSecurityToken.ACCOUNT_UPDATE,format = DataFormatEnum.JSON)
    public ResultBean<String> resetPassword(AccountDto dto){
        Assert.notNull(dto,"非法参数");
        Assert.notNull(dto.getId(),"账号Id不能为空");
        Account oldObj = this.accountFeign.getById(dto.getId());
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<String> resultBean = this.accountFeign.resetPassword(dto);
        if(null != resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(dto.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 修改账号密码
     * @param map 账号信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/modifyPassword")
//    @Security(token = PermissionsSecurityToken.ACCOUNT_UPDATE,format = DataFormatEnum.JSON)
    @Security(format = DataFormatEnum.JSON)
    public ResultBean<Boolean> modifyPassword(@RequestBody Map<String, String> map){
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        Assert.notNull(map,"非法参数");
        String oldPwd = map.get("oldPwd");
        String newPwd = map.get("newPwd");
        String confirmPwd = map.get("confirmPwd");

        Assert.notNull(oldPwd, "原密码不能为空");
        Assert.notNull(newPwd, "新密码不能为空");
        Assert.notNull(confirmPwd, "新密码不能为空");
        Assert.isTrue(DigestUtils.sha256Hex(oldPwd).equals(onLineUser.getLoginPwd()), "原密码不正确！");
        Assert.isTrue(!oldPwd.equals(newPwd), "新密码不能和旧密码相同");
        Assert.isTrue(confirmPwd.equals(newPwd), "两次输入的密码不一致");

        onLineUser.setLoginPwd(newPwd);

        ResultBean<Boolean> resultBean = this.accountFeign.modifyPassword(onLineUser);
        if(null != resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(onLineUser.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),onLineUser,onLineUser,onLineUser,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 删除账号
     * @param id 账号Id
     * @return ResultBean<Boolean>
     *
     *
     */
    @GetMapping(value = "/delete/{id}")
    @Security(token = PermissionsSecurityToken.ACCOUNT_DELETE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> delete(@PathVariable(value = "id")Long id){
        AccountDto dto = new AccountDto();
        dto.setId(id);
        Account oldObj = this.accountFeign.getById(id);
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<Boolean> resultBean =  this.accountFeign.deleteEntity(dto);
        if(null!= resultBean.getData() && resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.DELETE_EVENT,
                    WebUtils.getIp(),dto,onLineUser,oldObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述:批量删除账号
     * @param ids 选中的id集合
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/deleteAccountList")
    @Security(token = PermissionsSecurityToken.ACCOUNT_DELETE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> deleteAccountList(@RequestBody List<String> ids){
       if (null == ids || ids.size() <=0){
           //  参数异常
           return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
       }
       Account onLineUser = this.securityServiceInterface.getOnLineUser();
       AccountDto dto = new AccountDto();
       dto.setIds(ids);
       dto.setOnLineUser(onLineUser);
       ResultBean<Boolean> resultBean =  this.accountFeign.deleteAccountList(dto);
       if(null!= resultBean.getData() && resultBean.getData()){
           /*---------------------------------------------------记录日志--------------------------------------------------------*/
           SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.DELETE_EVENT,
                   WebUtils.getIp(),dto,onLineUser);
           sysOperationLogFeign.info(sysOperationLog);
           /*-------------------------------------------------------------------------------------------------------------------*/
       }
       return resultBean;
    }




    /**
     * 功能描述: 根据Id获取账号信息
     * @param id 账号Id
     * @return ResultBean<Account>
     *
     *
     */
    @GetMapping(value = "/get/{id}")
    public ResultBean<Account> getAccountById(@PathVariable(value = "id") Long id){
        //  获取账号信息
        Account account = this.accountFeign.getById(id);
        Assert.notNull(account,"账号Id不存在");
        //  获取当前用户信息
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        /*//  校验权限
        if (!account.getOrgPosition().startsWith(onLineUser.getOrgPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }*/
        //  获取此账号的角色列表
        List<Role> roleList = this.roleFeign.getListByAccountId(account.getId());
        account.setRoleList(roleList);
        //  获取用户所属机构
        Organization organization = this.orgFeign.getOrgById(account.getOrgId());
        account.setOrganization(organization);
        //  隐藏密码
        account.setLoginPwd(CommonConstant.HIDE);
        return new ResultBean<>(ResultEnum.SUCCESS,account);
    }

    /**
     * 功能描述: 开启或禁用账号信息
     * @param dto
     * {
     *     id       :   被禁用的账号Id
     *     isEnable :   { 1：开启，2：禁用 }
     * }
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/updateIsEnable")
    @Security(token = PermissionsSecurityToken.ACCOUNT_IS_ENABLE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> updateIsEnable(AccountDto dto){
        Assert.notNull(dto,"非法参数");
        Assert.notNull(dto.getId(),"账号Id不能为空");
        Assert.notNull(dto.getIsEnable(),"请设置账号开启或禁用");
        Account oldObj = this.accountFeign.getById(dto.getId());
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        //  获取当前登陆用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<Boolean> resultBean=this.accountFeign.updateIsEnable(dto);
        if(resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(dto.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),dto.getIsEnable()==1?"开启账号信息":"禁用账号信息",dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 开启或禁用账号小程序登录--实施小程序
     * @param dto
     * {
     *     id             :   被禁用的账号Id
     *     isWeChatLogin  :   { 1：开启，2：禁用 }
     * }
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/updateIsWeChatLogin")
    @Security(token = PermissionsSecurityToken.ACCOUNT_IS_WE_CHAT_LOGIN,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> updateIsWeChatLogin(AccountDto dto){
        Assert.notNull(dto,"非法参数");
        Assert.notNull(dto.getId(),"账号Id不能为空");
        Assert.notNull(dto.getIsWeChatLogin(),"请设置账号开启或禁用");
        Account oldObj = this.accountFeign.getById(dto.getId());
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        //  获取当前登陆用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<Boolean> resultBean=this.accountFeign.updateIsWeChatLogin(dto);
        if(resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(dto.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),dto.getIsWeChatLogin()==1?"开启账号小程序登录":"禁用账号信息小程序登录",dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 删除账号的openid--解绑微信
     * @param id 账号Id
     * @return ResultBean<Boolean>
     *
     *
     */
    @GetMapping(value = "/untiedWeChat/{id}")
    @Security(token = PermissionsSecurityToken.ACCOUNT_UNTIED_WE_CHAT,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> untiedWeChat(@PathVariable(value = "id")Long id){
        AccountDto dto = new AccountDto();
        dto.setId(id);
        Account oldObj = this.accountFeign.getById(dto.getId());
        if (oldObj == null){
            return new ResultBean<>(ResultEnum.NOT_FIND);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOnLineUser(onLineUser);
        ResultBean<Boolean> resultBean =  this.accountFeign.untiedWeChat(dto);
        if(null!= resultBean.getData() && resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Account newObj = this.accountFeign.getById(dto.getId());
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ACCOUNT_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }
}
