package com.testor.module.accident.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.biz.sys.dict.data.service.SysDictDataService;
import com.testor.biz.sys.dict.type.model.domain.SysDictType;
import com.testor.biz.sys.dict.type.service.SysDictTypeService;
import com.testor.biz.util.CacheDicUtils;
import com.testor.common.constant.DicTypeCode;
import com.testor.common.constant.ProcessStatus;
import com.testor.common.model.UpdateProcessStatusReq;
import com.testor.common.util.EnumUtil;
import com.testor.module.accident.model.domain.AccidentReport;
import com.testor.module.accident.model.dto.AccidentReportDelParam;
import com.testor.module.accident.model.req.*;
import com.testor.module.accident.model.resp.*;
import com.testor.module.accident.model.vo.AccidentReportVO;
import com.testor.module.accident.service.AccidentReportService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.biz.models.BaseResponseList;
import com.tongtech.tfw.backend.common.models.supers.SuperController;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Year;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 事故上报Controller
 *
 * @author zhangyangfan@testor.com.cn
 * @date 2022-05-11 11:35:33
 */
@RestController
@RequestMapping("/accident/report")
@Api(value = "AccidentReport", tags = "事故上报")
@Slf4j
public class AccidentReportController extends SuperController {
    @Autowired
    private AccidentReportService accidentReportService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private SysDictTypeService sysDictTypeService;
    @Autowired
    private SysDictDataService sysDictDataService;

    @ApiOperation(value = "获取节假日类型", notes = "获取节假日类型")
    @GetMapping(value = "/getFakeType")
    public BaseResponse<String> getFakeType(@RequestParam String dateFormat) throws Exception {
        BaseResponse<String> baseResponse = new BaseResponse<>();
        String url = "http://tool.bitefu.net/jiari/?d=" + dateFormat;
        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);
        baseResponse.setData(entity.getBody());
        return baseResponse;
    }


    @ApiOperation(value = "获取当前登录人前三级部门信息", notes = "获取当前登录人前三级部门信息")
    @GetMapping(value = "/getReportUnit")
    public BaseResponse<ReportUnitResp> getReportUnit() throws Exception {
        BaseResponse<ReportUnitResp> baseResponse = new BaseResponse<>();
        baseResponse.setData(accidentReportService.getReportUnit());
        return baseResponse;
    }

    /* Generated Method*/
    @ApiOperation(value = "新增 事故上报", notes = "Add AccidentReport")
    @PostMapping(value = "/add")
    public BaseResponse<AccidentReport> addEntity(@RequestBody AccidentReportInsReq accidentReportInsReq) throws Exception {
        BaseResponse<AccidentReport> baseResponse = new BaseResponse<>();
        AccidentReportInsResp accidentReportInsResp = accidentReportService.insertAll(accidentReportInsReq);
        baseResponse.setData(accidentReportInsResp);
        return baseResponse;
    }

    @ApiOperation(value = "获取 事故上报 ", notes = "Get AccidentReport By Id")
    @GetMapping(value = "/get")
    public BaseResponse<AccidentReportVO> getById(String id) throws Exception {
        BaseResponse<AccidentReportVO> baseResponse = new BaseResponse<>();
        baseResponse.setData(accidentReportService.getInfo(id));
        return baseResponse;
    }

    @ApiOperation(value = "修改 事故上报 ", notes = "Update AccidentReport By Id")
    @PutMapping(value = "/update")
    public BaseResponse<AccidentReportEditResp> updateEntity(@RequestBody AccidentReportEditReq accidentReportEditReq) throws Exception {
        BaseResponse<AccidentReportEditResp> baseResponse = new BaseResponse<>();
        AccidentReportEditResp accidentReportEditResp = accidentReportService.updateAll(accidentReportEditReq);
        baseResponse.setData(accidentReportEditResp);
        return baseResponse;
    }

    @ApiOperation(value = "删除事故上报 ", notes = "delete AccidentReport By Id")
    @PutMapping(value = "/physics/delete")
    public BaseResponse physicsDelete(@RequestBody AccidentReportDelParam deleteRequest) throws Exception {
//		if (ObjectHelper.isNotEmpty(deleteRequest) && StringHelper.isNotEmpty(deleteRequest.getId())) {
//			// TODO 按需求添加数据去重，特殊值设定，业务异常
//			AccidentReport data = new AccidentReport();
//			data.setId(deleteRequest.getId());
//			data.setStatus(BizConstants.STATUS_DELETE);
//			boolean result = accidentReportService.updateById(data);
//			baseResponse.setData(BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
//		}
        accidentReportService.physicsDelete(deleteRequest.getId());
        return BaseResponse.success();
    }

//	@ApiOperation(value = "批量删除事故上报", notes = "delete AccidentReport by batch Id")
//	@PutMapping(value = "/batch_delete")
//	public BaseResponse<BizGeneralResponse> deleteEntityBatch(@RequestBody AccidentReportDelParam deleteRequest) {
//		BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
//		if (ObjectHelper.isNotEmpty(deleteRequest) && (!deleteRequest.getIds().isEmpty())) {
//			/* 批量删除 */
//			List<AccidentReport> accidentReportList = new ArrayList<>();
//			for (String id : deleteRequest.getIds()) {
//				AccidentReport data = new AccidentReport();
//				data.setId(id);
//				data.setStatus(BizConstants.STATUS_DELETE);
//				accidentReportList.add(data);
//			}
//			boolean result = accidentReportService.updateBatchById(accidentReportList);
//			baseResponse.setData(BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
//		}
//		return baseResponse;
//	}

    @ApiOperation(value = "更新流程状态", notes = "更新审批流程状态")
    @PostMapping(value = "/updateProcessStatus")
    public BaseResponse updateProcessStatus(@RequestBody UpdateProcessStatusReq updateProcessStatusReq) throws Exception {
        accidentReportService.updateProcessStatus(updateProcessStatusReq);
        return BaseResponse.success();
    }


    @ApiOperation(value = "获取 事故上报 分页列表", notes = "List AccidentReport with page")
    @GetMapping(value = "/list")
    public BaseResponse<BaseResponseList<AccidentReportQueryResp>> listEntity(AccidentReportQueryReq param) throws Exception {
        BaseResponse<BaseResponseList<AccidentReportQueryResp>> baseResponse = new BaseResponse<>();
        Long page = StringHelper.isEmpty(param.getPage()) ? BizConstants.PAGE : Long.valueOf(param.getPage());
        Long limit = StringHelper.isEmpty(param.getLimit()) ? BizConstants.LIMIT : Long.valueOf(param.getLimit());
        Page<AccidentReport> resultPage = new Page<>(page, limit);
        QueryWrapper<AccidentReport> queryWrapper = accidentReportService.queryCondition(param);
        queryWrapper.apply(StringUtils.isNotBlank(param.getAccidentType())," FIND_IN_SET("+param.getAccidentType()+", accident_type) > 0");
        Page<AccidentReport> resultList = accidentReportService.page(resultPage, queryWrapper);
        BaseResponseList<AccidentReportQueryResp> baseResponseList = new BaseResponseList<>();
        if (CollectionUtils.isNotEmpty(resultList.getRecords())) {
            List<AccidentReportQueryResp> accidentReportQueryRespList = resultList.getRecords().stream()
                    .map(item -> {
                        ReportUnitResp reportUnitResp = JSONObject.parseObject(item.getReportUnit(), ReportUnitResp.class);
                        return AccidentReportQueryResp.builder()
                                .id(item.getId())
                                .regionalCompanyName(StringUtils.isNotBlank(item.getRegionalCompanyId()) ? reportUnitResp.getRegionalCompany() : "/")
                                .basicUnitName(StringUtils.isNotBlank(item.getBasicUnitId()) ? reportUnitResp.getBasicUnit() : "/")
                                .fullDept(reportUnitResp.getPath())
                                .accidentTypeName(CacheDicUtils.getByKeys(DicTypeCode.ACCIDENT_TYPE.name(), item.getAccidentType(), ","))
                                .accidentLevelName(CacheDicUtils.get(DicTypeCode.ACCIDENT_LEVEL.name(), item.getAccidentLevel()))
                                .accidentTime(item.getAccidentTime())
                                .processStatusName(StringUtils.isNotEmpty(item.getProcessStatus()) ? EnumUtil.getByCode(item.getProcessStatus(), ProcessStatus.class) : "")
                                .build();
                    }).collect(Collectors.toList());
            baseResponseList.setData(accidentReportQueryRespList);
        } else {
            baseResponseList.setData(new ArrayList<>());
        }
        baseResponseList.setTotal(resultList.getTotal());
        baseResponse.setData(baseResponseList);
        return baseResponse;
    }

//	@ApiOperation(value = "获取 事故上报 列表", notes = "List AccidentReport all")
//	@GetMapping(value = "/datas")
//	public BaseResponse<BaseResponseList<AccidentReport>> listAllEntity(AccidentReportQueryReq param) {
//		BaseResponse<BaseResponseList<AccidentReport>> baseResponse = new BaseResponse<>();
//		// TODO 根据需求修改查询条件及查询参数
//		QueryWrapper<AccidentReport> queryWrapper = this.createQuery(param);
//		List<AccidentReport> resultList = accidentReportService.list(queryWrapper);
//		BaseResponseList<AccidentReport> baseResponseList = new BaseResponseList<>();
//		baseResponseList.setData(resultList);
//		baseResponseList.setTotal(resultList.size());
//		baseResponse.setData(baseResponseList);
//		return baseResponse;
//	}

    /* Private Methods */

    @ApiOperation(value = "获取事故统计数据", notes = "根据条件获取事故统计数据")
    @GetMapping(value = "/getAccidentStatistics")
    public BaseResponse<AccidentStatisticsResp> getAccidentStatistics(AccidentStatisticsReq accidentStatisticsReq) throws Exception {
        BaseResponse<AccidentStatisticsResp> baseResponse = new BaseResponse<>();
        AccidentStatisticsResp accidentStatistics = accidentReportService.getAccidentStatistics(accidentStatisticsReq);
        baseResponse.setData(accidentStatistics);
        return baseResponse;
    }

    @ApiOperation(value = "事故上报导出校验", notes = "事故上报导出校验")
    @PostMapping(value = "/export/check")
    public BaseResponse export(@RequestBody AccidentReportExportReq accidentReportExportReq) throws Exception {
        accidentReportService.export(accidentReportExportReq);
        return BaseResponse.success();
    }


    @SneakyThrows
    @ApiOperation(value = "首页 - 未遂事故统计 - 年度累计")
    @GetMapping(value = "/yearNumber")
    public BaseResponse<Long> yearNumber(String orgId) {
        BaseResponse<Long> baseResponse = new BaseResponse<>();
        AccidentReportQueryReq accidentReportQueryReq = new AccidentReportQueryReq();
        String date = Year.now().getValue()+"-01-01";
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = formatter.parse(date);
        accidentReportQueryReq.setAccidentStartTime(parse);
        Long total = listEntity(accidentReportQueryReq).getData().getTotal();
        baseResponse.setData(total);
        return baseResponse;
    }

    @SneakyThrows
    @ApiOperation(value = "首页 - 未遂事故统计 - 年度累计列表")
    @GetMapping(value = "/yearNumberList")
    public BaseResponse<List<AccidentStatisticsResp.Pie>> yearNumberList(String orgId) {
        BaseResponse<List<AccidentStatisticsResp.Pie>> baseResponse = new BaseResponse<>();
        SysDictType sysDictTypeByAccidentType = sysDictTypeService.lambdaQuery().eq(SysDictType::getDictType, DicTypeCode.ACCIDENT_TYPE.name()).list().get(0);
        List<SysDictData> sysDictDataByAccidentTypeList = sysDictDataService.lambdaQuery().eq(SysDictData::getDictId, sysDictTypeByAccidentType.getDictId()).list();
        List<AccidentStatisticsResp.Pie> pieByTypeList = new ArrayList<>();

        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        List<AccidentReport> accidentReportList = accidentReportService.getAccidentReportByAccidentTime(year,orgId);

        //事故类型数据饼图结构赋值
        for (SysDictData sysDictData : sysDictDataByAccidentTypeList) {
            AccidentStatisticsResp.Pie pieByLevel = new AccidentStatisticsResp.Pie();
            //相应
            pieByLevel.setName(sysDictData.getDictValue());
            pieByLevel.setDictValue(sysDictData.getDictKey());
            //判断是否包含此类型id
            //long count = accidentReportList.stream().filter(accidentReport -> accidentReport.getAccidentType().contains(sysDictData.getDictKey())).count();
            AccidentReportQueryReq accidentReportQueryReq = new AccidentReportQueryReq();
            accidentReportQueryReq.setAccidentType(sysDictData.getDictKey());
            //当前年份
            String date = Year.now().getValue()+"-01-01";
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            Date parse = formatter.parse(date);
            accidentReportQueryReq.setAccidentStartTime(parse);
            Long total = listEntity(accidentReportQueryReq).getData().getTotal();
            //数量赋值
            pieByLevel.setValue(Math.toIntExact(total));
            pieByTypeList.add(pieByLevel);
        }

        BigDecimal base;

        pieByTypeList = pieByTypeList.stream().sorted(Comparator.comparing(AccidentStatisticsResp.Pie::getValue).reversed()).limit(5).collect(Collectors.toList());
        if (pieByTypeList.size() > 0) {
            AccidentStatisticsResp.Pie pie = pieByTypeList.get(0);
            Integer value = pie.getValue();
            base = new BigDecimal(value).multiply(new BigDecimal("1.2"));

            BigDecimal finalBase = base;
            pieByTypeList.forEach(pie1 -> {
                if (pie1.getValue() != 0) {
                    pie1.setRate(
                            new BigDecimal(pie1.getValue()).divide(finalBase, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).doubleValue()
                    );
                }
            });

//            pie1.getValue()/ finalBase * 100)
        }
        baseResponse.setData(pieByTypeList);
        return baseResponse;
    }
}
