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

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.common.cache.redis.util.RedisUtil;
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.platform.param.ticketSystem.*;
import com.liquidnet.service.platform.service.ticketSystem.ITicketSystemService;
import com.liquidnet.service.platform.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
    RedisUtil redisUtil;
    private final static String accessTokenKey = "ST:accessToken";

    @Override
    public String getAccessToken() {
        Object obj = redisUtil.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();
            redisUtil.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() + "");
        }
        if(fieldListParam.getCityId()!=0) {
            params.put("cityId", fieldListParam.getCityId() + "");
        }
        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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("venueCode", insertFieldParam.getVenueCode());
        params.add("provinceId", insertFieldParam.getProvinceId() + "");
        params.add("cityId", insertFieldParam.getCityId() + "");
        params.add("districtId", insertFieldParam.getDistrictId() + "");
        params.add("venueName", insertFieldParam.getVenueName());
        params.add("venueAddress", insertFieldParam.getVenueAddress());
        params.add("managementCompany", insertFieldParam.getManagementCompany());
        params.add("hasHall", insertFieldParam.getHasHall().toString());
        params.add("hallName", insertFieldParam.getHallName());
        params.add("hasSeat", insertFieldParam.getHasSeat().toString());
        params.add("seatNum", insertFieldParam.getSeatNum().toString());
        params.add("seatingCapacity", insertFieldParam.getSeatingCapacity().toString());
        ResponseDataVo<STFieldChangeVo> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/standard/venue/save", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<STFieldChangeVo>>() {
                        });
        return response.getData();
    }

    @Override
    public String insertPerformance(String accessToken, STInsertPerformanceParam insertPerformanceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("performanceId", insertPerformanceParam.getPerformanceId());
        params.add("performanceName", insertPerformanceParam.getPerformanceName());
        params.add("approval", insertPerformanceParam.getApproval());
        params.add("typeId", insertPerformanceParam.getTypeId().toString());
        params.add("posterUrl", insertPerformanceParam.getPosterUrl());
        params.add("performanceDesc", insertPerformanceParam.getPerformanceDesc());
        params.add("sponsor", insertPerformanceParam.getSponsor());
        params.add("performer", insertPerformanceParam.getPerformer());
        params.add("sessionList", JSON.toJSONString(insertPerformanceParam.getSessionList()));
        String response = HttpUtil.postRaw(ticketSystemUrl + "/performance/code", JSON.toJSONString(params), headers);
        return response;
    }

    @Override
    public boolean updatePerformance(String accessToken, STUpdatePerformanceParam updatePerformanceParam) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("performanceId", updatePerformanceParam.getPerformanceId());
        params.add("performanceName", updatePerformanceParam.getPerformanceName());
        params.add("approval", updatePerformanceParam.getApproval());
        params.add("typeId", updatePerformanceParam.getTypeId().toString());
        params.add("posterUrl", updatePerformanceParam.getPosterUrl());
        params.add("performanceDesc", updatePerformanceParam.getPerformanceDesc());
        params.add("sponsor", updatePerformanceParam.getSponsor());
        params.add("performer", updatePerformanceParam.getPerformer());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/performance/update", JSON.toJSONString(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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("sessionId", updateTimesParam.getSessionId());
        params.add("sessionCode", updateTimesParam.getSessionCode());
        params.add("sessionName", updateTimesParam.getSessionName());
        params.add("sessionStartTime", DateUtil.Formatter.yyyyMMddHHmmss.format(updateTimesParam.getSessionStartTime()));
        params.add("sessionEndTime", DateUtil.Formatter.yyyyMMddHHmmss.format(updateTimesParam.getSessionEndTime()));
        params.add("hallCode", updateTimesParam.getHallCode());
        params.add("hasSeat", updateTimesParam.getHasSeat().toString());
        params.add("performanceId", updateTimesParam.getPerformanceId());
        params.add("sessionStatus", updateTimesParam.getSessionStatus().toString());
        params.add("tag", updateTimesParam.getTag().toString());
        params.add("seatingChart", updateTimesParam.getSeatingChart());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/session/update", JSON.toJSONString(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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("sessionCode", insertTicketPriceParam.getSessionCode());
        params.add("priceList", JSON.toJSONString(insertTicketPriceParam.getPriceList()));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/inventory", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("performanceId", delTicketPriceParam.getPerformanceId());
        params.add("sessionCode", delTicketPriceParam.getSessionCode());
        params.add("priceId", delTicketPriceParam.getPriceId());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/inventory", JSON.toJSONString(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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("performanceId", insertTicketParam.getPerformanceId());
        params.add("sessionId", insertTicketParam.getSessionId());
        params.add("sessionCode", insertTicketParam.getSessionCode());
        params.add("priceId", insertTicketParam.getPriceId());
        params.add("ticketList", JSON.toJSONString(insertTicketParam.getTicketList()));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/ticket", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("performanceId", delTicketParam.getPerformanceId());
        params.add("sessionCode", delTicketParam.getSessionCode());
        params.add("priceId", delTicketParam.getPriceId());
        params.add("ticketId", delTicketParam.getTicketId());
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/deleteTicket", JSON.toJSONString(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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("orderId", insertOrderParam.getOrderId());
        params.add("orderTime", DateUtil.Formatter.yyyyMMddHHmmss.format(insertOrderParam.getOrderTime()));
        params.add("channelType", insertOrderParam.getChannelType().toString());
        params.add("channelName", insertOrderParam.getChannelName());
        params.add("ticketNum", insertOrderParam.getTicketNum().toString());
        params.add("totalAmount", insertOrderParam.getTotalAmount() + "");
        params.add("ticketType", insertOrderParam.getTicketType().toString());
        params.add("ticketMode", insertOrderParam.getTicketMode().toString());
        params.add("authMode", insertOrderParam.getAuthMode().toString());
        params.add("ticketOrderList", JSON.toJSONString(insertOrderParam.getTicketOrderList()));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/order", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("refundOrderId", refundOrderParam.getRefundOrderId());
        params.add("orderId", refundOrderParam.getOrderId());
        params.add("reason", refundOrderParam.getReason());
        params.add("refundOrderTime", DateUtil.Formatter.yyyyMMddHHmmss.format(refundOrderParam.getRefundOrderTime()));
        params.add("ticketOrderList", JSON.toJSONString(refundOrderParam.getTicketOrderList()));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/refundOrder", JSON.toJSONString(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");
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("accessToken", accessToken);
        params.add("ticketList", JSON.toJSONString(ticketList));
        ResponseDataVo<Boolean> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/report/checking", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<Boolean>>() {
                        });
        return response.getData();
    }
}
