package com.hz.pm.api.projectlib.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.ApiResponse;
import com.ningdatech.basic.model.PageVo;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.util.HmacAuthUtil;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.model.dto.ApplicationAppCodeSaveDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectApplication;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.vo.ProjectApplicationVO;
import com.hz.pm.api.projectlib.model.vo.ProjectDetailVO;
import com.hz.pm.api.projectlib.service.IProjectApplicationService;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.user.security.model.UserInfoDetails;
import com.hz.pm.api.user.util.LoginUserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * ApplicationManage
 * </p>
 *
 * @author ZPF
 * @since 14:19 2023/2/1
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ApplicationManage {

    @Value("${irs.app-report.url}")
    private String url;

    @Value("${irs.app-report.appKey}")
    private String appKey;

    @Value("${irs.app-report.appScret}")
    private String appScret;

    private final IProjectApplicationService applicationService;

    private final IProjectService projectService;

    /**
     * 保存 appCode
     *
     * @param dto
     * @return
     */
    public String saveAppCode(ApplicationAppCodeSaveDTO dto) {
        Long userId = LoginUserUtil.getUserId();
        ProjectApplication app = applicationService.getById(dto.getId());
        VUtils.isTrue(Objects.isNull(app)).throwMessage("该应用不存在");

        app.setAppCode(dto.getAppCode());
        app.setUpdateOn(LocalDateTime.now());
        app.setUpdateBy(userId);
        if (applicationService.updateById(app)) {
            return BizConst.SAVE_SUCCESS;
        }
        return BizConst.SAVE_FAIL;
    }

    /**
     * 获取试运行报告
     *
     * @param appCode
     * @return
     */
    public String getReport(String appCode) {
        String method = HttpMethod.GET.name();
        String appUrl = url + "?appCode=" + appCode;

        Map<String, String> header = HmacAuthUtil.generateHeader(appUrl, method, appKey, appScret);
        //请求头
        HttpHeaders headers = new HttpHeaders();

        for (Map.Entry<String, String> entry : header.entrySet()) {
            headers.add(entry.getKey(), entry.getValue());
        }
        //封装请求头
        HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(headers);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<ApiResponse> forEntity = restTemplate.exchange(appUrl, HttpMethod.GET, formEntity, ApiResponse.class);

        log.info("forEntity:", JSON.toJSONString(forEntity));
        log.info("body:", forEntity.getBody());
        ApiResponse body = forEntity.getBody();

        if (!body.getCode().equals(HttpStatus.OK.value())) {
            throw new BizException(body.getMessage());
        }

        Object data = body.getData();
        if (Objects.nonNull(data)) {
            JSONObject dataJson = JSON.parseObject(JSON.toJSONString(data));
            JSONArray resourceList = dataJson.getJSONArray("resourceList");
            if (CollUtil.isNotEmpty(resourceList)) {
                JSONObject resource = JSON.parseObject(JSON.toJSONString(resourceList.get(0)));
                if (StringUtils.isBlank(resource.getString("reportOss"))) {
                    //暂时没有 appCode 所以先返回测试数据
                    return "https://irs-yyyw.oss-cn-hangzhou-zwynet-d01-a.internet.cloud.zj.gov.cn/tmp/%E6%B8%A9%E5%B7%9E%E5%B8%82%E4%B9%90%E6%B8%85%E5%B8%82%E5%8C%BA%E5%9F%9F%E4%BD%93%E6%A3%80%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F_9cf0b901f2ca4fbf8ff274da359ad219.html?Expires=1687833685&OSSAccessKeyId=wMhEw2BhpIDc1xwO&Signature=UPAbMdDy23FI1sNemszg5WH%2BG40%3D";
                } else {
                    return resource.getString("reportOss");
                }
            }
        }
        throw new BizException("获取报告失败!");
    }

    /**
     * 查询 待注册的
     *
     * @param req
     * @return
     */
    public PageVo<ProjectDetailVO> toRegisterAppProjectLibList(ProjectListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        //建设单位 就是当前人的单位
        Page<Project> page = req.page();
        projectService.page(page, Wrappers.lambdaQuery(Project.class)
                .eq(Project::getStage, ProjectStatusEnum.NOT_APPROVED.getCode())
                .eq(Project::getStatus, ProjectStatusEnum.TO_BE_APP_REGISTER.getCode())
                .eq(Project::getBuildOrgCode, user.getMhUnitIdStr()));
        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.empty();
        }

        List<String> projectCodes = page.getRecords().stream().map(Project::getProjectCode).collect(Collectors.toList());
        //要去查询应用 此阶段 必定是 建设方案后的 所以直接查 建设方案的应用
        List<ProjectApplication> apps = applicationService.list(Wrappers.lambdaQuery(ProjectApplication.class)
                .in(ProjectApplication::getProjectCode, projectCodes)
                .eq(ProjectApplication::getIsConstruct, Boolean.TRUE));
        Map<String, List<ProjectApplication>> appMap = apps.stream().collect(Collectors.groupingBy(ProjectApplication::getProjectCode));
        List<ProjectDetailVO> res = page.getRecords().stream().map(p -> {
            ProjectDetailVO vo = BeanUtil.copyProperties(p, ProjectDetailVO.class);
            if (appMap.containsKey(p.getProjectCode())) {
                List<ProjectApplication> projectApplications = appMap.get(p.getProjectCode());
                vo.setProjectApplications(convert(projectApplications));
            }
            return vo;
        }).collect(Collectors.toList());

        return PageVo.of(res, page.getTotal());
    }

    private List<ProjectApplicationVO> convert(List<ProjectApplication> projectApplications) {
        if (CollUtil.isNotEmpty(projectApplications)) {
            return projectApplications.stream()
                    .map(a -> BeanUtil.copyProperties(a, ProjectApplicationVO.class))
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
}
