package com.njzscloud.supervisory.dispose.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.tuple.Tuple2;
import com.njzscloud.common.core.utils.GroupUtil;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.supervisory.dispose.contant.AuditStatus;
import com.njzscloud.supervisory.dispose.contant.GarbageCategory;
import com.njzscloud.supervisory.dispose.mapper.DisposeRecordMapper;
import com.njzscloud.supervisory.dispose.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处置记录
 */
@Slf4j
@Service
public class DisposeRecordService extends ServiceImpl<DisposeRecordMapper, DisposeRecordEntity> implements IService<DisposeRecordEntity> {

    /**
     * 新增
     *
     * @param disposeRecordEntity 数据
     */
    public void add(DisposeRecordEntity disposeRecordEntity) {
        this.save(disposeRecordEntity);
    }

    /**
     * 修改
     *
     * @param disposeRecordEntity 数据
     */
    public void modify(DisposeRecordEntity disposeRecordEntity) {
        this.updateById(disposeRecordEntity);
    }

    /**
     * 删除
     *
     * @param ids Ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        this.removeBatchByIds(ids);
    }

    /**
     * 详情
     *
     * @param id Id
     * @return DisposeRecordEntity 结果
     */
    public DisposeRecordEntity detail(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     *
     * @param disposeRecordPagingParam 筛选条件
     * @param pageParam                分页参数
     * @return PageResult&lt;DisposeRecordEntity&gt; 分页结果
     */
    public PageResult<DisposeRecordEntity> paging(PageParam pageParam, DisposeRecordPagingParam disposeRecordPagingParam) {
        String keywords = disposeRecordPagingParam.getKeywords();
        Page<DisposeRecordEntity> page = pageParam.toPage();
        page.addOrder(
                new OrderItem().setColumn("time_out_status").setAsc(false),
                new OrderItem().setColumn("id").setAsc(false)
        );
        return PageResult.of(this.page(page, Wrappers.<DisposeRecordEntity>lambdaQuery()
                .and(StrUtil.isNotBlank(keywords), it ->
                        it.like(DisposeRecordEntity::getOrigin, keywords)
                                .or().like(DisposeRecordEntity::getClearingCompany, keywords)
                                .or().like(DisposeRecordEntity::getLicensePlate, keywords)
                                .or().like(DisposeRecordEntity::getContact, keywords)
                                .or().like(DisposeRecordEntity::getContactPhone, keywords)
                                .or().like(DisposeRecordEntity::getDisposalSite, keywords)
                )
        ));
    }

    public byte[] export(List<LocalDate> date) {
        LocalDateTime start = LocalDateTime.of(date.get(0), LocalTime.of(0, 0));
        LocalDateTime end = LocalDateTime.of(date.get(1), LocalTime.of(23, 59));
        List<DisposeRecordExportResult> disposeRecordExportResults = baseMapper.export(start, end);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        EasyExcel.write(out, DisposeRecordExportResult.class).sheet("模板").doWrite(disposeRecordExportResults);
        return out.toByteArray();
    }

    public Map<String, Object> statistics(String date) {
        List<DisposeRecordStatisticsResult> list = baseMapper.statistics(date);
        Map<GarbageCategory, List<Tuple2<Integer, Double>>> map = GroupUtil.k_a(list, DisposeRecordStatisticsResult::getGarbageCategory, it -> Tuple2.create(it.getDisposeDay(), it.getTotalSuttleWeight()));


        DateTime time = DateUtil.parse(date + "-01 00:00:00");
        int dayOfMonth = DateUtil.endOfMonth(time).dayOfMonth();
        ArrayList<String> dayList = new ArrayList<>(dayOfMonth);

        for (int i = 0; i < dayOfMonth; i++) {
            dayList.add(i + 1 + "号");
        }


        HashMap<String, Double[]> series = new HashMap<>();
        for (GarbageCategory value : GarbageCategory.values()) {
            List<Tuple2<Integer, Double>> data = map.get(value);
            Map<Integer, Double> m = GroupUtil.k_o(data, Tuple2::get_0, Tuple2::get_1);
            Double[] dl = new Double[dayOfMonth];
            for (int i = 0; i < dayOfMonth; i++) {
                dl[i] = m.getOrDefault(i + 1, 0.0);
            }

            series.put(value.getTxt(), dl);
        }

        return MapUtil.<String, Object>builder()
                .put("xAxis", dayList)
                .put("series", series)
                .build();
    }

    public void report(Integer action, DisposeRecordReportParam disposeRecordReportParam) {
        switch (action) {
            case 1: {
                DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                        .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
                );
                if (disposeRecordEntity == null) {
                    this.save(resolveData(disposeRecordReportParam));
                    break;
                }
            }
            case 2: {
                DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                        .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
                );
                if (disposeRecordEntity != null) {
                    this.updateById(resolveData(disposeRecordReportParam).setId(disposeRecordEntity.getId()));
                } else {
                    throw Exceptions.clierr("更新失败，数据不存在");
                }
                break;
            }
            case 3: {
                DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                        .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
                );
                if (disposeRecordEntity != null) {
                    this.removeById(disposeRecordEntity.getId());
                } else {
                    throw Exceptions.clierr("删除失败，数据不存在");
                }
                break;
            }
            default:
                throw Exceptions.clierr("操作类型错误");
        }
        /* if (action == 1) {
            DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                    .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
            );
            if (disposeRecordEntity == null) {
                this.save(resolveData(disposeRecordReportParam));
            } else {
                throw Exceptions.clierr("新增失败，数据已存在");
            }
        } else if (action == 2) {
            DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                    .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
            );
            if (disposeRecordEntity != null) {
                this.updateById(resolveData(disposeRecordReportParam).setId(disposeRecordEntity.getId()));
            } else {
                throw Exceptions.clierr("更新失败，数据不存在");
            }
        } else if (action == 3) {
            DisposeRecordEntity disposeRecordEntity = this.getOne(Wrappers.lambdaQuery(DisposeRecordEntity.class)
                    .eq(DisposeRecordEntity::getDataSn, disposeRecordReportParam.getTreatmentOrderNo())
            );
            if (disposeRecordEntity != null) {
                this.removeById(disposeRecordEntity.getId());
            } else {
                throw Exceptions.clierr("删除失败，数据不存在");
            }
        } */
    }

    private DisposeRecordEntity resolveData(DisposeRecordReportParam disposeRecordReportParam) {
        Long startTime = disposeRecordReportParam.getStartTime();
        Long finishTime = disposeRecordReportParam.getFinishTime();
        LocalDateTime inTime = null;
        if (startTime != null && startTime > 0) {
            inTime = DateUtil.parse(startTime.toString()).toLocalDateTime();
        }
        LocalDateTime outTime = null;
        if (finishTime != null && finishTime > 0) {
            outTime = DateUtil.parse(finishTime.toString()).toLocalDateTime();
        }
        return new DisposeRecordEntity()
                .setOrigin(disposeRecordReportParam.getCommunityName())
                .setClearingCompany(disposeRecordReportParam.getClearCompanyName())
                .setGarbageCategory("ZSZY02".equals(disposeRecordReportParam.getGoodsCateSn()) ? GarbageCategory.ChaiQianLaJi : GarbageCategory.ZhuangXiuLaJi)
                .setLicensePlate(disposeRecordReportParam.getCarNo())
                .setInWeight(String.valueOf(disposeRecordReportParam.getGrossWeight() == null ? 0 : disposeRecordReportParam.getGrossWeight()))
                .setOutWeight(String.valueOf(disposeRecordReportParam.getTareWeight() == null ? 0 : disposeRecordReportParam.getTareWeight()))
                .setSuttleWeight(String.valueOf(disposeRecordReportParam.getNetWeight() == null ? 0 : disposeRecordReportParam.getNetWeight()))
                .setInTime(inTime)
                .setOutTime(outTime)
                .setDisposalSite(disposeRecordReportParam.getTreatmentCompanyName())
                .setDataSn(disposeRecordReportParam.getTreatmentOrderNo())
                .setInFrontPhoto(disposeRecordReportParam.getCarInFront())
                .setOutFrontPhoto(disposeRecordReportParam.getCarOutFront())
                .setInBodyPhoto(disposeRecordReportParam.getCarInBody())
                .setOutBodyPhoto(disposeRecordReportParam.getCarOutBody())
                .setContact(disposeRecordReportParam.getContact())
                .setContactPhone(disposeRecordReportParam.getContactPhone())
                .setTspPhotos(disposeRecordReportParam.getTspPhotos())
                .setZcPhotos(disposeRecordReportParam.getZcPhotos())
                ;

    }

    @Transactional(rollbackFor = Exception.class)
    public DisposeRecordEntity audit(AuditParam auditParam) {
        DisposeRecordEntity disposeRecordEntity = this.getById(auditParam.getId());
        Assert.notNull(disposeRecordEntity, () -> Exceptions.exception("数据不存在"));
        Assert.isTrue(disposeRecordEntity.getAuditStatus() == AuditStatus.DaiShenHe, () -> Exceptions.exception("数据已审核，不能重复审核"));
        this.updateById(new DisposeRecordEntity()
                .setId(disposeRecordEntity.getId())
                .setAuditStatus(auditParam.getAuditStatus())
                .setProblemDesc(auditParam.getProblemDesc())
        );
        return disposeRecordEntity;
    }
}
