package com.sqx.scheduler.export;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sqx.common.utils.SftpUtil;
import com.sqx.modules.app.entity.RechargeRecord;
import com.sqx.modules.app.service.RechargeRecordService;
import com.sqx.modules.app.service.UserMoneyDetailsService;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.datacentre.query.RankListQuery;
import com.sqx.modules.datacentre.query.ShopCenterQuery;
import com.sqx.modules.datacentre.service.DataCentreService;
import com.sqx.modules.exportExecl.dto.AccountEntry;
import com.sqx.modules.exportExecl.model.ExportJob;
import com.sqx.modules.exportExecl.service.ExportJobService;
import com.sqx.modules.order.dto.OrderQueryDto;
import com.sqx.modules.order.service.AppOrderService;
import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
import com.sqx.modules.pay.controller.query.WalletDetailQuery;
import com.sqx.modules.pay.service.CashOutService;
import com.sqx.modules.reconciliation.model.PlatformBillDto;
import com.sqx.modules.reconciliation.service.PlatformBillService;
import com.sqx.modules.utils.excel.ExcelData;
import com.sqx.modules.utils.excel.ExportExcelUtils;
import com.sqx.scheduler.config.SchedulerLock;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 优惠券定时任务
 *
 * @author : codingliang
 * @date : 2024-09-09 12:22
 */
@Slf4j
@Component
@RequiredArgsConstructor
@RequestMapping("/admin/aaaaaa")
public class ExportScheduler {

    private final CommonInfoService commonInfoService;
    private final RedissonClient redissonClient;
    private final RedisTemplate redisTemplate;
    private final ExportJobService exportJobService;
    private final AppOrderService appOrderService;
    private final RechargeRecordService rechargeRecordService;
    private final SftpUtil sftpUtil;
    private final CashOutService cashOutService;
    private final UserMoneyDetailsService userMoneyDetailsService;
    private final DataCentreService dataCentreService;
    private final PlatformBillService platformBillService;


    /**
     * 将所有超过失效时间的优惠券改为失效状态
     * 每分钟运行一次
     */
    @Async
    @Scheduled(cron = "18 */1 * * * ?", zone = "Asia/Shanghai")
//    @GetMapping("excelOrder")
    public void orderExport() throws Exception {
        List<ExportJob> exportJobList=exportJobService.list(new QueryWrapper<ExportJob>()
                .eq("flag",0).last("order by create_time limit 10"));
        log.info("本次导出数据exportJobList==========="+exportJobList);
        if (null == exportJobList ||exportJobList.isEmpty()){
            return;
        }
        int runningCount =exportJobService.count(new QueryWrapper<ExportJob>().eq("flag",-1));
        if (runningCount>=4){
            //同时执行的任务超过4条，不再新增任务
            return;
        }
        for(ExportJob exportJob:exportJobList){
            long bgTime = System.currentTimeMillis();
            String jobExecuteKey = SchedulerLock.EXPORT_LOCK + ":" + exportJob.getExportId();
            String jobExecuteRedisKey = SchedulerLock.EXPORT_LOCK +":R:" + exportJob.getExportId();
            RLock lock = redissonClient.getLock(jobExecuteKey);
            if (lock.tryLock(0, 5, TimeUnit.SECONDS)) {
                boolean isRedisKey = redisTemplate.hasKey(jobExecuteRedisKey);
                //rediskey避免重复导出
                if(isRedisKey){
                    log.info(exportJob.getExportId()+"已执行，跳过");
                    continue;
                }
                redisTemplate.opsForValue().set(jobExecuteRedisKey, "LOCK", 5, TimeUnit.MINUTES);
                //设置为执行中
                exportJob.setFlag(-1);
                exportJob.setUpdateTime(new Date());
                exportJobService.updateById(exportJob);
                String fileName=exportJob.getFileName();
                String fileType=exportJob.getFileType();
                InputStream inputStream=null;
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                try {
                    ExcelData excelData=new ExcelData();
                    if("order".equals(fileType)){
                        excelData=getOrderExcelData(exportJob);
                    }else if("recharge".equals(fileType)){
                        excelData=getRechargeOrderExcelData(exportJob);
                    }else if("payouts".equals(fileType)){
                        excelData=getPayoutsExcelData(exportJob);
                    }else if("deposit".equals(fileType)){
                        excelData=getDepositExcelData(exportJob);
                    }else if("shopCenter".equals(fileType)){
                        excelData=getShopCenterExcelData(exportJob);
                    }else if("accountEntry".equals(fileType)){
                        excelData=getAccountEntryExcelData(exportJob);
                    }else if("rankList".equals(fileType)){
                        excelData=getRankListExcelData(exportJob);
                    }else if("riderBill".equals(fileType)){
                        excelData=getRiderBillExcelData(exportJob);
                    }else if("shopBill".equals(fileType)){
                        excelData=getShopBillExcelData(exportJob);
                    }else if("platformBill".equals(fileType)){
                        excelData=getPlatformBillExcelData(exportJob);
                    }else{
                        continue;
                    }
                    String value=commonInfoService.findOne(430).getValue();
                    ExportExcelUtils.writeExcel2(os,fileName,excelData);
                    byte[] buffer = os.toByteArray();
                    inputStream = new ByteArrayInputStream(buffer);
                    double fileSize = os.size();
                    double fileSizeKB = new BigDecimal(fileSize/1024).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); //转换单位为KB
                    exportJob.setFileSize(String.valueOf(fileSizeKB));
                    exportJob.setFlag(1);
                    exportJob.setUpdateTime(new Date());
                    sftpUtil.login();
                    sftpUtil.upload(value,fileName,inputStream);
                    exportJobService.updateById(exportJob);
                } catch (Exception e) {
                    exportJob.setUpdateTime(new Date());
                    exportJob.setFlag(2);
                    exportJobService.updateById(exportJob);
                    log.error(e.toString());
                } finally {
                    try {
                        if (lock.isLocked()) {
                            lock.unlock();
                        }
                        if(os!=null){
                            os.close();
                        }
                        if(inputStream!=null){
                            inputStream.close();
                        }
                        if(sftpUtil.isConnected()){
                            sftpUtil.logout();
                        }
                    } catch (RuntimeException re) {
                        log.error("报表解锁失败");
                    }
                }
            }
            long edTime = System.currentTimeMillis();
            log.info("执行：通用数据导出定时任务"+exportJob.getExportId()+"......执行任务完成,执行时长：{} s", (edTime - bgTime) / 1000);
        }
    }



    //订单导出
    private ExcelData getOrderExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        OrderQueryDto queryDto =new OrderQueryDto();
        if(!"".equals(conditions[1])){
            queryDto.setStatus(Integer.valueOf(conditions[1]));
        }
        queryDto.setPhone(conditions[2]);
        if(!"".equals(conditions[3])){
            queryDto.setShopId(Long.valueOf(conditions[3]));
        }
        queryDto.setUserName(conditions[4]);
        queryDto.setOrderNumber(conditions[5]);
        if(!"".equals(conditions[6])){
            queryDto.setOrderType(Integer.valueOf(conditions[6]));
        }
        queryDto.setShopName(conditions[7]);
        queryDto.setRiderPhone(conditions[8]);
        queryDto.setStartTime(conditions[9]);
        queryDto.setEndTime(conditions[10]);
        queryDto.setPayStartTime(conditions[11]);
        queryDto.setPayEndTime(conditions[12]);
        if(!"".equals(conditions[13])){
            queryDto.setRiderStationId(Integer.valueOf(conditions[13]));
        }
        queryDto.setShopTypeId(conditions[14]);
        queryDto.setCouponType(conditions[15]);
        queryDto.setIndentStatus(conditions[16]);
        queryDto.setRefundStartTime(conditions[17]);
        queryDto.setRefundEndTime(conditions[18]);

        return appOrderService.excelAllOrderAdmin(queryDto);
    }

    //充值记录导出
    private ExcelData getRechargeOrderExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        String rechargeOrder=conditions[1];
        String acount=conditions[2];
        QueryWrapper<RechargeRecord> qw=new QueryWrapper<RechargeRecord>();
        if(StringUtils.hasText(rechargeOrder)){
            qw.eq("order_no",rechargeOrder);
        }
        if(StringUtils.hasText(acount)){
            qw.eq("user_phone",acount);
        }
        ExcelData data = new ExcelData();
        data.setName("订单列表");
        List<String> titles = new ArrayList<>();
        titles.add("用户id");titles.add("编号");titles.add("充值金额");titles.add("充值前余额");
        titles.add("充值后余额"); titles.add("被充值账号（手机号）");titles.add("被充值名称");titles.add("被充值昵称");
        titles.add("被充值头像"); titles.add("更新时间");titles.add("充值时间");titles.add("充值人账号");
        titles.add("备注");
        data.setTitles(titles);
        List<RechargeRecord> recordList=rechargeRecordService.list(qw);
        List<List<Object>> rows = new ArrayList<>();
        for (RechargeRecord record:recordList){
            List<Object> row = new ArrayList<>();
            row.add(record.getUserId());
            row.add(record.getOrderNo());
            row.add(record.getAmount());
            row.add(record.getOldMoney());
            row.add(record.getBalance());
            row.add(record.getUserPhone());
            row.add(record.getUserName());
            row.add(record.getUserNick());
            row.add(record.getUserAvatar());
            row.add(record.getUpdateTime());
            row.add(record.getCreateTime());
            row.add(record.getAccount());
            row.add(record.getRemark());
            rows.add(row);
        }
        data.setRows(rows);
        return data;
    }

    //提现管理导出
    private ExcelData getPayoutsExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        CashOutQueryDTO queryDTO =new CashOutQueryDTO();
        queryDTO.setZhifubaoName(conditions[1]);
        queryDTO.setZhifubao(conditions[2]);
        queryDTO.setShopName(conditions[3]);
        if(!"".equals(conditions[4])){
            queryDTO.setState(Integer.valueOf(conditions[4]));
        }
        queryDTO.setType(conditions[5]);
        queryDTO.setStartTime(conditions[6]);
        queryDTO.setEndTime(conditions[7]);
        queryDTO.setRiderStationId(conditions[8]);
        queryDTO.setOutStartTime(conditions[9]);
        queryDTO.setOutEndTime(conditions[10]);
        queryDTO.setUserName(conditions[11]);
        queryDTO.setPhone(conditions[12]);
        return cashOutService.excelPayDetails(queryDTO);
    }

    //导出保证金记录
    private ExcelData getDepositExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        WalletDetailQuery queryDTO =new WalletDetailQuery();
        queryDTO.setShopName(conditions[1]);
        queryDTO.setType(conditions[2]);
        queryDTO.setClassify(conditions[3]);
        queryDTO.setStartTime(conditions[4]);
        queryDTO.setEndTime(conditions[5]);

        return userMoneyDetailsService.excelWalletDetails(queryDTO);
    }

    //导出商铺收益排行
    private ExcelData getShopCenterExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        ShopCenterQuery query =new ShopCenterQuery();
        query.setShopType(conditions[3]);
        query.setStartTime(conditions[1]);
        query.setEndTime(conditions[2]);
        query.setDate(conditions[4]);
        query.setDateType(conditions[5]);
        return dataCentreService.excelShopCenter(query);
    }
    //导出入账管理
    private ExcelData getAccountEntryExcelData(ExportJob exportJob) {
        String[] conditions=exportJob.getConditions().split(",",-1);
        AccountEntry query =new AccountEntry();
        query.setShopName(conditions[1]);
        query.setShopPhone(conditions[2]);
        query.setUserPhone(conditions[3]);
        query.setCouponName(conditions[4]);
        query.setOrderNumber(conditions[5]);
        query.setStartTime(conditions[6]);
        query.setEndTime(conditions[7]);
        query.setFlag(conditions[8]);
        return userMoneyDetailsService.excelAccountEntry(query);
    }
    //导出骑手收益排行
    private ExcelData getRankListExcelData(ExportJob exportJob){
        String[] conditions=exportJob.getConditions().split(",",-1);
        RankListQuery query =new RankListQuery();
        query.setAddress(conditions[1]);
        query.setDateType(conditions[2]);
        query.setDate(conditions[3]);
        query.setRiderStationId(conditions[4]);
        return dataCentreService.excelRankingList(query);
    }
    private ExcelData getRiderBillExcelData(ExportJob exportJob) {
        PlatformBillDto query = getPlatformBillDto(exportJob);
        return platformBillService.excelRiderBillList(query);
    }

    private static @NotNull PlatformBillDto getPlatformBillDto(ExportJob exportJob) {
        String[] conditions= exportJob.getConditions().split(",",-1);
        PlatformBillDto query =new PlatformBillDto();
        query.setStartDate(conditions[1]);
        query.setEndDate(conditions[2]);
        query.setRiderName(conditions[3]);
        query.setRiderPhone(conditions[4]);
        query.setShopName(conditions[5]);
        query.setShopPhone(conditions[6]);
        query.setRiderStation(conditions[7]);
        return query;
    }

    private ExcelData getShopBillExcelData(ExportJob exportJob) {
        PlatformBillDto query = getPlatformBillDto(exportJob);
        return platformBillService.excelShopBillList(query);
    }
    private ExcelData getPlatformBillExcelData(ExportJob exportJob) {
        PlatformBillDto query = getPlatformBillDto(exportJob);
        return platformBillService.excelPlatformBillList(query);
    }
}
