package com.liquidnet.service.platform.service.ticketSystem.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.dto.param.ticketSystem.*;
import com.liquidnet.service.platform.service.ticketSystem.ITicketSystemService;
import com.liquidnet.service.kylin.dto.vo.ticketSystem.*;
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.util.HashMap;
import java.util.List;

/**
 * <p>
 * 票务对接平台 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-11
 */
@Service
@Slf4j
public class ITicketSystemServiceImpl implements ITicketSystemService {
    @Value("${liquidnet.service.other.ticketSystemUrl}")
    private String ticketSystemUrl;
    @Value("${liquidnet.service.other.appId}")
    private String appId;
    @Value("${liquidnet.service.other.secret}")
    private String secret;
    @Autowired
    RedisDataSourceUtil redisDataSourceUtil;
    private final static String accessTokenKey = "ST:accessToken";

    @Override
    public String getAccessToken() {
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(accessTokenKey);
        if (obj != null) {
            return (String) obj;
        } else {
            MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
            headers.add("Accept", "application/json;charset=UTF-8");
            HashMap<String, String> params = CollectionUtil.mapStringString();
            params.put("appId", appId);
            params.put("secret", secret);
            ResponseDataVo<STAccessTokenVo> response =
                    JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/getAccessToken", JSON.toJSONString(params), headers),
                            new TypeReference<ResponseDataVo<STAccessTokenVo>>() {
                            });
            String accessToken = response.getData().getAccessToken();
            redisDataSourceUtil.getRedisKylinUtil().set(accessTokenKey, accessToken, (response.getData().getExpiresIn() - 60));
            return accessToken;
        }
    }

    @Override
    public List<STPTListVo> getPerformanceTypeList(String accessToken) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        String json = HttpUtil.getRaw(ticketSystemUrl + "/standard/performance/type/list?accessToken={accessToken}", JSON.toJSONString(params), headers);
        ResponseDataVo<List<STPTListVo>> response =
                JsonUtils.fromJson(json, new TypeReference<ResponseDataVo<List<STPTListVo>>>() {
                });
        return response.getData();
    }

    @Override
    public List<STFieldListVo> getFieldList(String accessToken, STFieldListParam fieldListParam) {
        String url = ticketSystemUrl + "/standard/venue/list";//
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("pageNo", fieldListParam.getPageNo().toString());
        params.put("pageSize", fieldListParam.getPageSize().toString());
        if (fieldListParam.getProvinceId() != 0) {
            params.put("provinceId", fieldListParam.getProvinceId() + "");
//            params.put("provinceId", 110000 + "");
        }
        if (fieldListParam.getCityId() != 0) {
            params.put("cityId", fieldListParam.getCityId() + "");
//            params.put("cityId", 110100 + "");
        }
        if (fieldListParam.getDistrictId() != 0) {
            params.put("districtId", fieldListParam.getDistrictId() + "");
        }
        if (fieldListParam.getVenueName() != null) {
            params.put("venueName", fieldListParam.getVenueName());
        }
        log.debug("URL = " + url);
        log.debug("params = " + JSON.toJSONString(params));
        ResponseListVo<List<STFieldListVo>> response =
                JsonUtils.fromJson(HttpUtil.postRaw(url, JSON.toJSONString(params), headers),
                        new TypeReference<ResponseListVo<List<STFieldListVo>>>() {
                        });
        return response.getData().getDataList();
    }

    @Override
    public STFieldChangeVo insertField(String accessToken, STInsertFieldParam insertFieldParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("venueCode", insertFieldParam.getVenueCode());
        params.put("provinceId", insertFieldParam.getProvinceId() + "");
//        params.put("provinceId", 110000 + "");
        params.put("cityId", insertFieldParam.getCityId() + "");
//        params.put("cityId", 110100 + "");

        params.put("districtId", insertFieldParam.getDistrictId() + "");
        params.put("venueName", insertFieldParam.getVenueName());
        params.put("venueAddress", insertFieldParam.getVenueAddress());
        params.put("managementCompany", insertFieldParam.getManagementCompany());
        params.put("hasHall", insertFieldParam.getHasHall().toString());
        params.put("hallName", insertFieldParam.getHallName());
        params.put("hasSeat", insertFieldParam.getHasSeat() == null ? null : insertFieldParam.getHasSeat().toString());
        params.put("seatNum", insertFieldParam.getSeatNum() == null ? null : insertFieldParam.getSeatNum().toString());
//        params.put("seatingCapacity", insertFieldParam.getSeatingCapacity() == null ? null : insertFieldParam.getSeatingCapacity().toString());
        params.put("seatingCapacity", "1");
        log.debug("URL = " + ticketSystemUrl + "/standard/venue/save");
        log.debug("params = " + JSON.toJSONString(params));
        ResponseDataVo<STFieldChangeVo> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/standard/venue/save", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<STFieldChangeVo>>() {
                        });
        return response.getData();
    }

    @Override
    public JSONObject insertPerformance(String accessToken, STInsertPerformanceParam insertPerformanceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("performanceId", insertPerformanceParam.getPerformanceId());
        params.put("performanceName", insertPerformanceParam.getPerformanceName());
        if (insertPerformanceParam.getApproval() != null) {
            params.put("approval", insertPerformanceParam.getApproval());
        }
        params.put("typeId", insertPerformanceParam.getTypeId().toString());
        params.put("posterUrl", insertPerformanceParam.getPosterUrl());
        params.put("sessionList", JSON.toJSONString(insertPerformanceParam.getSessionList()));
        ResponseDataVo<JSONObject> response = JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/performance/code", getJsonStr(params), headers),
                new TypeReference<ResponseDataVo<JSONObject>>() {
                });
        return response.getData();
    }

    @Override
    public boolean updatePerformance(String accessToken, STUpdatePerformanceParam updatePerformanceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("performanceId", updatePerformanceParam.getPerformanceId());
        params.put("performanceName", updatePerformanceParam.getPerformanceName());
        params.put("approval", updatePerformanceParam.getApproval());
        params.put("typeId", updatePerformanceParam.getTypeId().toString());
        params.put("posterUrl", updatePerformanceParam.getPosterUrl());
        params.put("performanceDesc", updatePerformanceParam.getPerformanceDesc());
        params.put("sponsor", updatePerformanceParam.getSponsor());
        params.put("performer", updatePerformanceParam.getPerformer());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/performance/update", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    @Override
    public boolean updateTimes(String accessToken, STUpdateTimesParam updateTimesParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("sessionId", updateTimesParam.getSessionId());
        params.put("sessionCode", updateTimesParam.getSessionCode());
        params.put("sessionName", updateTimesParam.getSessionName());
        params.put("sessionStartTime", DateUtil.Formatter.yyyyMMddHHmmss.format(updateTimesParam.getSessionStartTime()));
        params.put("sessionEndTime", DateUtil.Formatter.yyyyMMddHHmmss.format(updateTimesParam.getSessionEndTime()));
        params.put("hallCode", updateTimesParam.getHallCode());
        params.put("hasSeat", updateTimesParam.getHasSeat().toString());
        params.put("performanceId", updateTimesParam.getPerformanceId());
        params.put("sessionStatus", updateTimesParam.getSessionStatus().toString());
        params.put("tag", updateTimesParam.getTag().toString());
        params.put("seatingChart", updateTimesParam.getSeatingChart());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/session/update", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    @Override
    public boolean insertTicketPrice(String accessToken, STInsertTicketPriceParam insertTicketPriceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("sessionCode", insertTicketPriceParam.getSessionCode());
        params.put("priceList", JSON.toJSONString(insertTicketPriceParam.getPriceList()));
        log.debug("JSON = " + getJsonStr(params));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/inventory", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        log.debug("RESULT = " + response);
        return response.getData();
    }

    @Override
    public boolean delTicketPrice(String accessToken, STDelTicketPriceParam delTicketPriceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("performanceId", delTicketPriceParam.getPerformanceId());
        params.put("sessionCode", delTicketPriceParam.getSessionCode());
        params.put("priceId", delTicketPriceParam.getPriceId());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/inventory", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    @Override
    public boolean insertTicket(String accessToken, STInsertTicketParam insertTicketParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("performanceId", insertTicketParam.getPerformanceId());
        params.put("sessionId", insertTicketParam.getSessionId());
        params.put("sessionCode", insertTicketParam.getSessionCode());
        params.put("priceId", insertTicketParam.getPriceId());
        params.put("ticketList", JSON.toJSONString(insertTicketParam.getTicketList()));
        log.debug("JSON = " + getJsonStr(params));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/ticket", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        log.debug("RESULT = " + response);
        return response.getData();
    }

    @Override
    public boolean delTicket(String accessToken, STDelTicketParam delTicketParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("performanceId", delTicketParam.getPerformanceId());
        params.put("sessionCode", delTicketParam.getSessionCode());
        params.put("priceId", delTicketParam.getPriceId());
        params.put("ticketId", delTicketParam.getTicketId());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/deleteTicket", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    @Override
    public boolean insertOrder(String accessToken, STInsertOrderParam insertOrderParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("orderId", insertOrderParam.getOrderId());
        params.put("orderTime", insertOrderParam.getOrderTime());
        params.put("channelType", insertOrderParam.getChannelType().toString());
        params.put("channelName", insertOrderParam.getChannelName());
        params.put("ticketNum", insertOrderParam.getTicketNum().toString());
        params.put("totalAmount", insertOrderParam.getTotalAmount() + "");
        params.put("ticketType", insertOrderParam.getTicketType().toString());
        params.put("ticketMode", insertOrderParam.getTicketMode().toString());
        params.put("authMode", insertOrderParam.getAuthMode().toString());
        params.put("ticketOrderList", JSON.toJSONString(insertOrderParam.getTicketOrderList()));
        log.debug("JSON = " + getJsonStr(params));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/order", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        log.debug("RESULT = " + response);
        return response.getData();
    }

    @Override
    public boolean refundOrder(String accessToken, STRefundOrderParam refundOrderParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("refundOrderId", refundOrderParam.getRefundOrderId());
        params.put("orderId", refundOrderParam.getOrderId());
        params.put("reason", refundOrderParam.getReason());
        params.put("refundOrderTime", DateUtil.Formatter.yyyyMMddHHmmss.format(refundOrderParam.getRefundOrderTime()));
        params.put("ticketOrderList", JSON.toJSONString(refundOrderParam.getTicketOrderList()));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/refundOrder", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    @Override
    public boolean insertCheck(String accessToken, List<CheckVo> ticketList) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        HashMap<String, String> params = CollectionUtil.mapStringString();
        params.put("accessToken", accessToken);
        params.put("ticketList", JSON.toJSONString(ticketList));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/checking", getJsonStr(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }

    private String getJsonStr(HashMap<String, String> params) {
        return JSON.toJSONString(params).replaceAll("\\\\", "").replaceAll("\"\\[", "\\[").replaceAll("]\"", "]");
    }
}
