package com.yuchen.saas.park.service.controller.log;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thinkunion.park.service.common.baseentity.MenuTypeEnum;
import com.yuchen.saas.manage.user.api.entity.User;
import com.yuchen.saas.manage.user.api.entity.UserInfoEntity;
import com.yuchen.saas.manage.user.api.feign.IUserClient;
import com.yuchen.saas.manage.user.api.request.UserNameRequest;
import com.yuchen.saas.park.api.dto.menu.MenuDto;
import com.yuchen.saas.park.api.dto.park.QueryOperationLogDto;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.park.PmgBatParkUserOperationLog;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.PmgBatParkUserOperationLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nest.springwrap.core.mp.base.BaseEntity;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.DateUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author 黄兵华
 * @date 2022/1/13 16:22
 * @describe
 */
@Api(tags = "操作日志记录")
@RestController
@RequestMapping("/operationLog")
public class PmgBatParkUserOperationLogController {


    @Resource
    private PmgBatParkUserOperationLogService operationLogService;

    @Resource
    private PmgBatParkInfoService parkInfoService;

    @Autowired
    private IUserClient iUserClient;

    @PostMapping("/getOperationPage")
    @ApiOperation(value = "操作记录查询", notes = "操作记录查询")
    public R<IPage<PmgBatParkUserOperationLog>> getOperationPage(@RequestBody QueryOperationLogDto operationLogDto){
        List<Long> userIds=new ArrayList<>();
        List<Long> userInfoIds=new ArrayList<>();
        if(StrUtil.isNotBlank(operationLogDto.getUserName())){
            R<List<User>>userListResult= iUserClient.userByAccount(operationLogDto.getUserName());
            if(userListResult.isSuccess()){
                userIds=userListResult.getData().stream().map(User::getId).collect(Collectors.toList());
            }
            R<List<UserInfoEntity>>userInfoListResult= iUserClient.userInfoByName(operationLogDto.getUserName());
            if(userInfoListResult.isSuccess()){
                userInfoIds=userInfoListResult.getData().stream().map(UserInfoEntity::getId).collect(Collectors.toList());
            }
        }

        Page<PmgBatParkUserOperationLog> page = new Page<>();
        page.setCurrent(operationLogDto.getCurrent());
        LambdaQueryWrapper<PmgBatParkUserOperationLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(PmgBatParkUserOperationLog::getCreateTime);
        if (ObjectUtil.isNotNull(MenuTypeEnum.getMenuTypeByDesc(operationLogDto.getMenuName()))) {
            wrapper.eq(
                    PmgBatParkUserOperationLog::getOperationType,
                    MenuTypeEnum.getMenuTypeByDesc(operationLogDto.getMenuName()).getValue()
                    );
        }
        if (ObjectUtil.isNotNull(operationLogDto.getMenuTypeEnum())) {
            wrapper.eq(ObjectUtil.isNotNull(operationLogDto.getMenuTypeEnum()),PmgBatParkUserOperationLog::getOperationType,
                    operationLogDto.getMenuTypeEnum().getValue()
                    );
        }
        wrapper.eq(ObjectUtil.isNotNull(operationLogDto.getUserId()),
                PmgBatParkUserOperationLog::getUserId ,
                operationLogDto.getUserId());

        //CreateUser 用来存放账户id,UserId用来存放userInfoId
        List<Long> finalUserIds = userIds;
        List<Long> finalUserInfoIds = userInfoIds;
        wrapper.and(StrUtil.isNotBlank(operationLogDto.getUserName()),a -> a
                .or(StrUtil.isNotBlank(operationLogDto.getUserName()),item -> item
                        .like(PmgBatParkUserOperationLog::getUserName ,
                                operationLogDto.getUserName()))
                .or(Func.isNotEmpty(finalUserIds),item -> item
                        .in(PmgBatParkUserOperationLog::getCreateUser ,
                                finalUserIds))
                .or(Func.isNotEmpty(finalUserInfoIds),item -> item
                        .in(PmgBatParkUserOperationLog::getUserId ,
                                finalUserInfoIds))
        );

        wrapper.eq(StrUtil.isNotBlank(operationLogDto.getParkId()),
                PmgBatParkUserOperationLog::getParkId ,
                operationLogDto.getParkId());

        wrapper.ge(ObjectUtil.isNotNull(operationLogDto.getRequestTimeStart()) ,
                PmgBatParkUserOperationLog::getRequestTime,
                operationLogDto.getRequestTimeStart());
        wrapper.le(ObjectUtil.isNotNull(operationLogDto.getRequestTimeEnd()) ,
                PmgBatParkUserOperationLog::getRequestTime,
                operationLogDto.getRequestTimeEnd());
        wrapper.ge(ObjectUtil.isNotNull(operationLogDto.getUseTimeMin()) ,
                PmgBatParkUserOperationLog::getUseTime,
                operationLogDto.getUseTimeMin());
        wrapper.le(ObjectUtil.isNotNull(operationLogDto.getUseTimeMax()) ,
                PmgBatParkUserOperationLog::getUseTime,
                operationLogDto.getUseTimeMax());
        wrapper.in(PmgBatParkUserOperationLog::getOperationType,MenuTypeEnum.getUseValue());
        page.setSize(operationLogDto.getSize());
        Page<PmgBatParkUserOperationLog> operationLogPage = operationLogService.page(page, wrapper);
        List<String> parkIds = operationLogPage.getRecords().stream().filter(var -> StrUtil.isNotBlank(var.getParkId())).map(PmgBatParkUserOperationLog::getParkId)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(parkIds)){
            Map<Long, String> map = parkInfoService.list(new LambdaQueryWrapper<PmgBatParkInfo>().in(PmgBatParkInfo::getId, parkIds)).stream().collect(Collectors.toMap(
                    BaseEntity::getId,
                    PmgBatParkInfo::getParkName,
                    (v1, v2) -> v2
            ));
            operationLogPage.getRecords().forEach(var-> var.setParkName(map.get(Long.parseLong(var.getParkId()))));
        }
       List<UserNameRequest> requestList= operationLogPage.getRecords().stream().map(a->{
            UserNameRequest request= new UserNameRequest();
            request.setId(a.getId());
            request.setUserId(a.getCreateUser());
            request.setUserInfoId(a.getUserId());
            return request;
        }).collect(Collectors.toList());
        R<Map<Long,String>>result= iUserClient.userNameById(requestList);

        operationLogPage.getRecords().forEach(var->{
            MenuTypeEnum typeEnum = MenuTypeEnum.getMenuTypeByValue(var.getOperationType());
            var.setMenuName(Optional.ofNullable(typeEnum).map(MenuTypeEnum::getDesc).orElse(""));

            if(result.isSuccess()){
                if(result.getData().containsKey(var.getId())&& Func.isNotEmpty(result.getData().get(var.getId()))){
                    var.setNickName(result.getData().get(var.getId()));
                }
            }
        });
        return R.data(operationLogPage);
    }


    @GetMapping("/getMenuName")
    @ApiOperation(value = "操作菜单下拉框", notes = "操作菜单下拉框")
    public R<List<MenuDto>> getMenuName(){
        List<MenuDto> menuDtoList = new ArrayList<>();
        MenuTypeEnum.getUserMenuName().forEach(var->{
            menuDtoList.add(new MenuDto(var,var.getDesc()));
        });
        return R.data(menuDtoList);
    }

    @PostMapping("/save")
    @ApiOperation(value = "保存用户操作数据", notes = "保存用户操作数据")
    public R saveLog(@RequestBody PmgBatParkUserOperationLog log){

        return R.data(operationLogService.save(log));
    }
}
