package com.xiang.xservice.application.script.fwd.schedule;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xiang.xmc.service.schedule.core.DynamicTaskScheduler;
import com.xiang.xmc.service.schedule.entity.ScheduledTaskEntity;
import com.xiang.xmc.service.schedule.entity.TaskConfig;
import com.xiang.xmc.service.schedule.enums.TaskGroupEnum;
import com.xiang.xmc.service.schedule.enums.TaskStatusEnum;
import com.xiang.xmc.service.schedule.service.IDynamicTaskSchedulerService;
import com.xiang.xservice.application.script.fwd.entity.param.FwdOrderTaskParam;
import com.xiang.xservice.application.script.fwd.entity.pojo.FPerformConfig;
import com.xiang.xservice.application.script.fwd.entity.pojo.FPerformProjectInfo;
import com.xiang.xservice.application.script.fwd.entity.pojo.FPerformSeatInfo;
import com.xiang.xservice.application.script.fwd.entity.pojo.FUserConfig;
import com.xiang.xservice.application.script.fwd.entity.resp.http.perform.Perform;
import com.xiang.xservice.application.script.fwd.entity.resp.http.perform.PerformDetail;
import com.xiang.xservice.application.script.fwd.entity.resp.http.perform.PerformInfo;
import com.xiang.xservice.application.script.fwd.entity.resp.http.perform.SeatPlan;
import com.xiang.xservice.application.script.fwd.entity.resp.http.perform.SeatPlanStatus;
import com.xiang.xservice.application.script.fwd.mapper.FwdAudienceConfigMapper;
import com.xiang.xservice.application.script.fwd.mapper.FwdPerformConfigMapper;
import com.xiang.xservice.application.script.fwd.mapper.FwdPerformProjectInfoMapper;
import com.xiang.xservice.application.script.fwd.mapper.FwdUserConfigMapper;
import com.xiang.xservice.application.script.fwd.service.DingTalkScriptFWDService;
import com.xiang.xservice.application.script.fwd.service.IPerformService;
import com.xiang.xservice.application.script.fwd.service.IPerformServiceHttp;
import com.xiang.xservice.application.script.fwd.utils.TimeSyncUtils;
import com.xiang.xservice.basic.utils.DateUtils;
import com.xiang.xservice.basic.utils.PrimaryKeyUtils;
import com.xiang.xservice.common.entity.SysConfigDO;
import com.xiang.xservice.common.mapper.SysConfigMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: xiang
 * @Date: 2025-07-25 14:13
 */
@Component
@RequiredArgsConstructor
@Slf4j
@RestController
@RequestMapping("/system/job/fwd")
public class FwdImportantMsgJob {

    private final FwdPerformProjectInfoMapper performProjectInfoMapper;
    private final FwdPerformConfigMapper performConfigMapper;
    private final DynamicTaskScheduler dynamicTaskScheduler;
    private final DingTalkScriptFWDService dingTalkScriptFWDService;
    private final FwdUserConfigMapper fwdUserConfigMapper;
    private final FwdAudienceConfigMapper fwdAudienceConfigMapper;
    private final IPerformService iPerformService;
    private final IDynamicTaskSchedulerService dynamicTaskSchedulerService;
    private final IPerformServiceHttp iPerformServiceHttp;
    private final SysConfigMapper sysConfigMapper;

    @PostConstruct
    public void init() {
        log.info("xs-fwd任务调度系统初始化！");
        ScheduledTaskEntity scheduledTaskEntity = new ScheduledTaskEntity();
        scheduledTaskEntity.setTaskGroup(TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode());
        scheduledTaskEntity.setStatus(TaskStatusEnum.UN_START.getCode());
        List<ScheduledTaskEntity> taskList = dynamicTaskSchedulerService.getTaskList(scheduledTaskEntity);
        for (ScheduledTaskEntity taskEntity : taskList) {
            HashMap params = com.alibaba.fastjson2.JSON.parseObject(taskEntity.getParameters(), HashMap.class);
            FwdOrderTaskParam param = MapUtils.isEmpty(params) ? new FwdOrderTaskParam(null, taskEntity.getId()) : new FwdOrderTaskParam(Long.parseLong(params.get("projectId").toString()), taskEntity.getId());
            LocalDateTime runTime = taskEntity.getRunTime().isBefore(TimeSyncUtils.now()) ? TimeSyncUtils.now() : taskEntity.getRunTime();
            dynamicTaskScheduler.schedule(
                    new TaskConfig(taskEntity.getId(), taskEntity.getTaskName(), taskEntity.getTaskGroup(), runTime, params),
                    new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, param, dynamicTaskSchedulerService),
                    TimeSyncUtils.now()
            );
        }
    }

    @Scheduled(cron = "0 0 8 1/1 * ?")
    @PostMapping("/preSaleReminderJob")
    public void preSaleReminderJob() throws Exception {
        log.info("【芬玩岛】演唱会预售定时任务开始！time:{}", System.currentTimeMillis());

        // 删除配置表里面今日配置的项目信息
        performConfigMapper.delPerforms();

        // 查询所有即将今天预售的演唱会信息
        LocalDate now = TimeSyncUtils.now().toLocalDate();
        List<FPerformProjectInfo> saleTodayData = performProjectInfoMapper.getPreSaleTodayData(now.atTime(0, 0, 0), now.atTime(23, 59, 59));
        if (CollectionUtils.isEmpty(saleTodayData)) {
            log.info("【芬玩岛】 今天:{}暂无预售的演唱会门票信息.", now);
            return;
        }
        log.info("【芬玩岛】 即将:{}预售的演唱会门票信息:{}", now, JSONObject.toJSONString(saleTodayData));
        List<FPerformConfig> addList = saleTodayData.stream().map(data -> {
            FPerformConfig performConfig = new FPerformConfig();
            performConfig.setTime(data.getPreSaleTime());
            performConfig.setProjectId(data.getProjectId());
            performConfig.setDelFlag(0);
            return performConfig;
        }).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addList)) {
            performConfigMapper.insertPerforms(addList);
        }

        // 是否下单开关
        boolean flag = false;
        SysConfigDO config = sysConfigMapper.getByName("fwd.order.create.switch");
        if (Objects.nonNull(config)) {
            if (StringUtils.isNotBlank(config.getValue())) {
                if (StringUtils.equals(config.getValue(), "true")) {
                    flag = true;
                }
            }
        }

        StringBuilder msg = new StringBuilder("今日" + now + "演唱会门票预售信息:\n");
        for (FPerformProjectInfo data : saleTodayData) {
            msg.append("演唱会名称：").append(data.getProjectName()).append("预售时间:").append(DateUtils.getDateTimeFromDateTime(data.getPreSaleTime())).append("\n");
            long taskId = PrimaryKeyUtils.snowflakeId();
            Map<String, Object> params = Maps.newHashMap();
            params.put("projectId", data.getProjectId());
            LocalDateTime runTime = data.getPreSaleTime().isBefore(LocalDateTime.now()) ? LocalDateTime.now().plusMinutes(1) : data.getPreSaleTime();
            if (flag) {
                dynamicTaskScheduler.schedule(
                        new TaskConfig(taskId, "芬玩岛演唱会抢票-【" + data.getProjectName()  + "】", TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode(),
                                runTime, params),
                        new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService,
                                new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService),
                        TimeSyncUtils.now());
                savaTask(data, taskId, params);
            }
        }
        msg.append("请注意进行数据库配置的更改！");
        dingTalkScriptFWDService.sendScriptMsg(msg.toString());
        log.info("【芬玩岛】演唱会预售定时任务结束！time:{}", System.currentTimeMillis());
    }

    @Scheduled(cron = "0 10 8 1/1 * ?")
    @PostMapping("/presaleSeatReminderJob")
    public void  presaleSeatReminderJob() {

        List<FUserConfig> availableUser = fwdUserConfigMapper.getAvailableUser();
        String token = availableUser.get(0).getToken();

        ScheduledTaskEntity entity = new ScheduledTaskEntity();
        entity.setStatus(TaskStatusEnum.UN_START.getCode());
        List<ScheduledTaskEntity> taskList = dynamicTaskSchedulerService.getTaskList(entity);
        if (CollectionUtils.isEmpty(taskList)) {
            log.info("今天暂无预售的演出，time:{}", LocalDateTime.now());
            return;
        }
        log.info("今天:{}的预售的项目信息:{}", LocalDateTime.now(), JSON.toJSONString(taskList));
        LocalDateTime todayStartTime = LocalDate.now().atTime(0, 0, 0);
        LocalDateTime todayEndTime = LocalDate.now().atTime(23, 59, 59);

        StringBuffer msg = new StringBuffer();

        taskList.forEach(taskEntity -> {
            String parameters = taskEntity.getParameters();
            JSONObject jsonObject = JSON.parseObject(parameters);
            Long projectId = null;
            try {
                projectId = (Long) jsonObject.get("projectId");
            } catch (Exception e) {
                log.error("异常错误信息:{}", JSON.toJSONString(taskEntity), e);
            }
            if (Objects.nonNull(projectId)) {
                Perform performsByProjectIdFromHttp = iPerformServiceHttp.getPerformsByProjectIdFromHttp(projectId, token);
                if (Objects.nonNull(performsByProjectIdFromHttp)) {
                    for (PerformInfo performInfo : performsByProjectIdFromHttp.getPerformInfos()) {
                        for (PerformDetail performDetail : performInfo.getPerformInfo()) {
                            LocalDateTime saleTime = DateUtils.getDateTimeFromStr(performDetail.getSaleTime());
                            if (saleTime.isAfter(todayStartTime) && saleTime.isBefore(todayEndTime)) {
                                List<SeatPlan> seatPlans = performDetail.getSeatPlans();
                                Map<Long, SeatPlan> seatPlanMap = seatPlans.stream().collect(Collectors.toMap(SeatPlan::getSeatPlanId, Function.identity(), (a, b) -> a));
                                List<Long> seatPlanIds = seatPlans.stream().map(SeatPlan::getSeatPlanId).collect(Collectors.toList());
                                List<SeatPlanStatus> seatPlanStatusFromHttp = iPerformServiceHttp.getSeatPlanStatusFromHttp(seatPlanIds, token);
                                for (SeatPlanStatus seatPlanStatus : seatPlanStatusFromHttp) {
                                    if (!seatPlanStatus.getSoldOutFlag()) {
                                        FPerformSeatInfo seatInfoBySeatId = iPerformService.getSeatInfoBySeatId(seatPlanStatus.getSeatPlanId());
                                        if (Objects.nonNull(seatInfoBySeatId)) {
                                            seatInfoBySeatId.setSoldOut(0);
                                            iPerformService.updateSeatInfo(seatInfoBySeatId);
                                            msg.append("演出任务名称").append(taskEntity.getTaskName()).append("的场次信息")
                                                    .append(performDetail.getName()).append("的座位信息")
                                                    .append(seatInfoBySeatId.getSeatPlanName()).append("信息已更新\n");
                                        } else {
                                            if (seatPlanMap.containsKey(seatPlanStatus.getSeatPlanId())) {
                                                SeatPlan seatPlan = seatPlanMap.get(seatPlanStatus.getSeatPlanId());
                                                FPerformSeatInfo fPerformSeatInfo = new FPerformSeatInfo();
                                                fPerformSeatInfo.setSeatPlanId(seatInfoBySeatId.getSeatPlanId());
                                                fPerformSeatInfo.setSeatPlanName(seatPlan.getSeatPlanName());
                                                fPerformSeatInfo.setPerformId(seatInfoBySeatId.getPerformId());
                                                fPerformSeatInfo.setPerformName(seatInfoBySeatId.getPerformName());
                                                fPerformSeatInfo.setStopSale(seatInfoBySeatId.getStopSale());
                                                fPerformSeatInfo.setShelfStatus(seatInfoBySeatId.getShelfStatus());
                                                fPerformSeatInfo.setPrice(seatInfoBySeatId.getPrice());
                                                fPerformSeatInfo.setDiscountPrice(seatInfoBySeatId.getDiscountPrice());
                                                fPerformSeatInfo.setSubStatus(seatInfoBySeatId.getSubStatus());
                                                fPerformSeatInfo.setQuantity(seatInfoBySeatId.getQuantity());
                                                fPerformSeatInfo.setStatus(seatInfoBySeatId.getStatus());
                                                fPerformSeatInfo.setMaxSellStock(seatInfoBySeatId.getMaxSellStock());
                                                fPerformSeatInfo.setSoldStock(seatInfoBySeatId.getSoldStock());
                                                fPerformSeatInfo.setLeftStock(seatInfoBySeatId.getLeftStock());
                                                fPerformSeatInfo.setAbleSaleQuantity(seatInfoBySeatId.getAbleSaleQuantity());
                                                fPerformSeatInfo.setAshShow(seatInfoBySeatId.getAshShow());
                                                fPerformSeatInfo.setAshShowDesc(seatInfoBySeatId.getAshShowDesc());
                                                fPerformSeatInfo.setSelectable(seatInfoBySeatId.getSelectable());
                                                fPerformSeatInfo.setDisplay(seatInfoBySeatId.getDisplay());
                                                fPerformSeatInfo.setAvailableTicketQuantity(seatInfoBySeatId.getAvailableTicketQuantity());
                                                fPerformSeatInfo.setAvailableAllTicketQuantity(seatInfoBySeatId.getAvailableAllTicketQuantity());
                                                fPerformSeatInfo.setSaleTime(seatInfoBySeatId.getSaleTime());
                                                fPerformSeatInfo.setProjectId(seatInfoBySeatId.getProjectId());
                                                fPerformSeatInfo.setSoldOut(seatInfoBySeatId.getSoldOut());
                                                iPerformService.addSeatInfo(fPerformSeatInfo);
                                                msg.append("演出任务名称").append(taskEntity.getTaskName()).append("的场次信息")
                                                        .append(performDetail.getName()).append("的座位信息")
                                                        .append(seatPlan.getSeatPlanName()).append("信息已更新\n");
                                            }
                                        }

                                    } else {
                                        log.info("演出:{}，座位:{}，已售罄", performDetail.getName(), seatPlanStatus.getSeatPlanId());
                                        msg.append("演出任务名称").append(taskEntity.getTaskName()).append("的场次信息")
                                                .append(performDetail.getName()).append("的座位信息").append("已售罄\n");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        dingTalkScriptFWDService.sendScriptMsg(msg.toString());
    }

    private void savaTask(FPerformProjectInfo data, long taskId, Map<String, Object> params) {
        ScheduledTaskEntity entity = new ScheduledTaskEntity();
        entity.setId(taskId);
        entity.setTaskName("芬玩岛演唱会抢票-【" + data.getProjectName() + "】");
        entity.setTaskGroup(TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode());
        entity.setRunTime(data.getPreSaleTime());
        entity.setStatus(TaskStatusEnum.UN_START.getCode());
        entity.setParameters(JSON.toJSONString(params));
        entity.setCreatedTime(LocalDateTime.now());
        entity.setUpdatedTime(LocalDateTime.now());
        dynamicTaskSchedulerService.saveTask(entity);
    }
}
