package com.liquidnet.client.admin.zhengzai.kylin.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.client.admin.zhengzai.goblin.utils.GoblinObjectUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.DataUtils;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.param.ticketSystem.*;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.ticketSystem.*;
import com.liquidnet.service.slime.dto.vo.SlimeFieldsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;

@Service
@Slf4j
public class InnerService {

    @Value("${liquidnet.service.platform.url}")
    private String platform;
    //    private String platform = "http://127.0.0.1:9003";
    @Autowired
    RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    DataUtils dataUtils;

    //上报演出
    public List<String> reportP(KylinPerformanceVo vo, String approval, String sponsorId) {
        STInsertPerformanceParam insertPerformanceParam = STInsertPerformanceParam.getNew();
        insertPerformanceParam.setPerformanceId(vo.getPerformancesId());
        insertPerformanceParam.setPerformanceName(vo.getTitle());
        if (approval != null) {
            insertPerformanceParam.setApproval(approval);
        }
        insertPerformanceParam.setTypeId(vo.getType() == 101 ? 2002 : 2003);
        insertPerformanceParam.setPosterUrl(vo.getImgPoster());
        insertPerformanceParam.setSponsor(sponsorId);
        //场次相关
        List<TimesVo> timesVos = new ArrayList();
        List<KylinTicketTimesVo> kylinTimeVos = vo.getTicketTimeList();
        for (KylinTicketTimesVo item : kylinTimeVos) {
            TimesVo timesVo = TimesVo.getNew();
            timesVo.setSessionId(item.getTicketTimesId());
            timesVo.setSessionName(item.getTitle());
            timesVo.setHallCode(getVenueCode(vo.getFieldId()));
            timesVo.setSessionStartTime(item.getUseStart());
            String endTime = LocalDateTime.parse(item.getUseEnd() == null ? timesVo.getSessionStartTime() : item.getUseEnd(), DTF_YMD_HMS).plusDays(1).minusSeconds(1L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            timesVo.setSessionEndTime(endTime);
            timesVo.setHasSeat(0);
            timesVos.add(timesVo);
        }
        insertPerformanceParam.setSessionList(timesVos);
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String resultData = HttpUtil.postRaw(platform + "/platform/st/performance/insert", JSON.toJSONString(insertPerformanceParam), header);
        ResponseDto<JSONObject> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<JSONObject>>() {
        });
        List<String> sessionCodeList = CollectionUtil.linkedListString();
        for (KylinTicketTimesVo item : kylinTimeVos) {
            JSONObject jobj = innerReturnVo.getData();
            String sessionCode = jobj.getString(item.getTicketTimesId());
            sessionCodeList.add(sessionCode);
            setSessionCode(item.getTicketTimesId(), sessionCode);
        }
        for (KylinTicketTimesVo item : vo.getTicketTimeList()) {
            reportTP(item.getTicketList(), getSessionCode(item.getTicketTimesId()), vo.getPerformancesId(), item.getTicketTimesId());
        }

        return sessionCodeList;
    }

    //修改上报的演出项目数据
    public boolean updateP(KylinTicketTimesVo vo, String performanceId, String fieldId) {
        STUpdateTimesParam updateTimesParam = STUpdateTimesParam.getNew();
        updateTimesParam.setSessionId(vo.getTicketTimesId());
        updateTimesParam.setSessionCode(getSessionCode(vo.getTicketTimesId()));
        updateTimesParam.setSessionName(vo.getTitle());
        updateTimesParam.setSessionStartTime(LocalDateTime.parse(vo.getUseStart(), DTF_YMD_HMS));
        updateTimesParam.setSessionEndTime(LocalDateTime.parse(vo.getUseEnd(), DTF_YMD_HMS));
        updateTimesParam.setHallCode(getVenueCode(getVenueCode(fieldId)));
        updateTimesParam.setHasSeat(0);
        updateTimesParam.setPerformanceId(performanceId);
        updateTimesParam.setSessionStatus(1);
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String resultData = HttpUtil.postRaw(platform + "/platform/performance/update", JSON.toJSONString(updateTimesParam), header);
        ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
        });
        return innerReturnVo.getData();
    }

    //更新上报的场次数据
    public boolean updateTT(KylinPerformanceVo vo, String approval, String sponsorId) {
        STUpdatePerformanceParam updatePerformanceParam = STUpdatePerformanceParam.getNew();
        updatePerformanceParam.setPerformanceId(vo.getPerformancesId());
        updatePerformanceParam.setPerformanceName(vo.getTitle());
        updatePerformanceParam.setTypeId(vo.getType() == 101 ? 2002 : 2003);
        updatePerformanceParam.setPosterUrl(vo.getImgPoster());
        updatePerformanceParam.setSponsor(sponsorId);
        updatePerformanceParam.setApproval(approval);
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String resultData = HttpUtil.postRaw(platform + "/platform/times/update", JSON.toJSONString(updatePerformanceParam), header);
        ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
        });
        return innerReturnVo.getData();
    }

    //上报票价信息
    private boolean reportTP(List<KylinTicketVo> vo, String sessionCode, String performanceId, String ticketTimeId) {
        STInsertTicketPriceParam insertTicketPriceParam = STInsertTicketPriceParam.getNew();
        insertTicketPriceParam.setSessionCode(sessionCode);
        List<TicketPriceVo> priceVos = new ArrayList();
        for (KylinTicketVo item : vo) {
            TicketPriceVo priceVo = TicketPriceVo.getNew();
            priceVo.setPerformanceId(performanceId);
            priceVo.setSessionId(ticketTimeId);
            priceVo.setPriceId(getPriceId(item.getTicketsId()));
            priceVo.setPriceName(item.getTitle());
            priceVo.setTicketPrice(item.getPrice().multiply(BigDecimal.valueOf(100)).intValue());
            priceVo.setAvailableInventory(item.getTotalGeneral());
            priceVo.setUnavailableInventory(0);//工作人员位置等 无座位无用
            priceVos.add(priceVo);
        }
        insertTicketPriceParam.setPriceList(priceVos);
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String resultData = HttpUtil.postRaw(platform + "/platform/st/ticketPrice/insert", JSON.toJSONString(insertTicketPriceParam), header);
        ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
        });
        reportT(performanceId, getSessionCode(ticketTimeId), vo, ticketTimeId);
        return innerReturnVo.getData();
    }

    //上报票信息
    private boolean reportT(String performanceId, String sessionCode, List<KylinTicketVo> ticketIdList, String ticketTimeId) {
        STInsertTicketParam insertTicketParam = STInsertTicketParam.getNew();
        insertTicketParam.setPerformanceId(performanceId);
        insertTicketParam.setSessionId(ticketTimeId);
        insertTicketParam.setSessionCode(sessionCode);
        List<TicketVo> ticketVos = new ArrayList();
        for (KylinTicketVo item : ticketIdList) {
            insertTicketParam.setPriceId(getPriceId(item.getTicketsId()));
            TicketVo ticketVo = TicketVo.getNew();
            ticketVo.setTicketId(item.getTicketsId());
            ticketVo.setAvailableSale(1);
            ticketVos.add(ticketVo);
        }
        insertTicketParam.setTicketList(ticketVos);
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String resultData = HttpUtil.postRaw(platform + "/platform/st/ticket/insert", JSON.toJSONString(insertTicketParam), header);
        ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
        });
        return innerReturnVo.getData();
    }

    //上报场地
    public boolean reportField(SlimeFieldsVo vo) {
        try {
            MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
            headers.add("Accept", "application/json;charset=UTF-8");
            MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
            params.add("provinceId", vo.getProvinceId());
            params.add("cityId", vo.getCityId());
            params.add("districtId", vo.getDistrictId());
            params.add("pageNo", "1");
            params.add("pageSize", "40");
            params.add("venueName", vo.getName());
            String json = HttpUtil.post(platform + "/platform/st/field/list", params, headers);
            ResponseDataVo<List<STFieldListVo>> response =
                    JsonUtils.fromJson(json, new TypeReference<ResponseDataVo<List<STFieldListVo>>>() {
                    });
            STInsertFieldParam insertTicketParam = STInsertFieldParam.getNew();
            if (response.getData() != null && response.getData().size() >= 1) {
                STFieldListVo innerVo = response.getData().get(0);
                setVenueCode(vo.getFieldId(), innerVo.getVenueCode());
                return true;
            } else {
                insertTicketParam.setVenueCode(getVenueCode(vo.getFieldId()));
                insertTicketParam.setProvinceId(Integer.parseInt(vo.getProvinceId()));
                insertTicketParam.setCityId(Integer.parseInt(vo.getCityId()));
                insertTicketParam.setDistrictId(Integer.parseInt(vo.getDistrictId()));
                insertTicketParam.setVenueName(vo.getName());
                insertTicketParam.setVenueAddress(vo.getAddress());
                insertTicketParam.setManagementCompany(null);
                insertTicketParam.setHasHall(0);
                insertTicketParam.setHallName(null);
                insertTicketParam.setHasSeat(0);
                insertTicketParam.setSeatNum(null);
                insertTicketParam.setSeatingCapacity(null);
                MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
                header.add("Accept", "application/json;charset=UTF-8");
                String resultData = HttpUtil.postRaw(platform + "/platform/st/field/insert", JSON.toJSONString(insertTicketParam), header);
                ResponseDto<STFieldChangeVo> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<STFieldChangeVo>>() {
                });
                setVenueCode(vo.getFieldId(), innerReturnVo.getData().getVenueCode());
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //退款订单 todo 需要结合退款接口处理
    public boolean reportRefund(String orderId, String refundOrderId, String reason) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
        STRefundOrderParam param = STRefundOrderParam.getNew();
        param.setOrderId(orderId);
        param.setReason(reason);
        param.setRefundOrderId(refundOrderId);
        param.setRefundOrderTime(LocalDateTime.now());
        List<RefundOrderVo> refundOrderVos = new ArrayList();
        for (KylinOrderTicketEntitiesVo entitiesVo : orderTicketVo.getEntitiesVoList()) {
            RefundOrderVo refundOrderVo = RefundOrderVo.getNew();
            refundOrderVo.setRefundAmount(entitiesVo.getRefundPrice().multiply(BigDecimal.valueOf(100)).toString());
            refundOrderVo.setSessionCode(getSessionCode(entitiesVo.getTimeId()));
            refundOrderVo.setTicketId(entitiesVo.getTicketId());
            refundOrderVo.setTicketOrderId(entitiesVo.getOrderTicketEntitiesId());
            refundOrderVos.add(refundOrderVo);
        }
        param.setTicketOrderList(refundOrderVos);

        String resultData = HttpUtil.postRaw(platform + "/platform/st/order/refund", JSON.toJSONString(param), headers);
        ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
        });
        return innerReturnVo.getData();
    }

    //上报订单
    public boolean reportO(KylinOrderTicketVo vo, String channelName) {
        try {
            if (vo.getStatus() == 2 || vo.getStatus() == 4) {
                log.info("订单状态 不需要同步");
                return false;
            }
            STInsertOrderParam insertOrderParam = STInsertOrderParam.getNew();
            insertOrderParam.setOrderId(vo.getOrderTicketsId());
            insertOrderParam.setOrderTime(vo.getTimePay());
            insertOrderParam.setChannelType(1);
            insertOrderParam.setChannelName(channelName);
            insertOrderParam.setTicketNum(vo.getNumber());
            insertOrderParam.setTotalAmount(vo.getPriceActual().multiply(BigDecimal.valueOf(100)).intValue());
            insertOrderParam.setTicketType(1);
            insertOrderParam.setTicketMode(vo.getGetTicketType().equalsIgnoreCase("express") ? 1 : 2);
            insertOrderParam.setAuthMode(dataUtils.getPerformanceIsTrueName(vo.getPerformanceId()) == 1 ? 3 : 1);
            int voucherPrice = vo.getPriceVoucher().multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(vo.getNumber())).intValue();
            int refundPrice = vo.getPriceRefund().multiply(BigDecimal.valueOf(100)).intValue();
            List<OrderVo> orderVos = GoblinObjectUtils.orderVo();
            for (KylinOrderTicketEntitiesVo item : vo.getEntitiesVoList()) {
                if (item.getIsPayment() == 0 || item.getIsPayment() == 3) {
                    log.info("票单状态 不需要同步");
                    continue;
                }
                OrderVo orderVo = OrderVo.getNew();
                orderVo.setTicketOrderId(item.getOrderTicketEntitiesId());
                orderVo.setPerformanceId(item.getPerformanceId());
                orderVo.setSessionId(item.getTimeId());
                orderVo.setSessionCode(getSessionCode(item.getTimeId()));
                orderVo.setPriceId(getPriceId(item.getTicketId()));
                orderVo.setTicketPrice((vo.getPrice().subtract(vo.getPriceRefund())).multiply(BigDecimal.valueOf(100)).intValue());
                orderVo.setTicketId(item.getOrderTicketEntitiesId());
                orderVo.setTicketOrderAmount(orderVo.getTicketPrice() - voucherPrice - refundPrice);
                orderVos.add(orderVo);
            }
            insertOrderParam.setTicketOrderList(orderVos);
            MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
            header.add("Accept", "application/json;charset=UTF-8");
            String resultData = HttpUtil.postRaw(platform + "/platform/st/order/insert", JSON.toJSONString(insertOrderParam), header);
            ResponseDto<Boolean> innerReturnVo = JsonUtils.fromJson(resultData, new TypeReference<ResponseDto<Boolean>>() {
            });
            return innerReturnVo.getData();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //设置SessionCode
    private void setSessionCode(String ticketTimeId, String sessionCode) {
        redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.TIMES_SESSION_CODE.concat(ticketTimeId), sessionCode);
    }

    //获取SessionCode
    private String getSessionCode(String ticketTimeId) {
        return (String) redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.TIMES_SESSION_CODE.concat(ticketTimeId));
    }

    private String getPriceId(String ticketId) {
        return ticketId.concat("01");
    }

    private String getVenueCode(String fieldId) {
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.TIMES_VENUE_CODE.concat(fieldId));
        if (obj == null) {
            return null;
        } else {
            return (String) obj;
        }
    }

    private void setVenueCode(String fieldId, String venueCode) {
        redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.TIMES_VENUE_CODE.concat(fieldId), venueCode);
    }
}
