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.STFieldListParam;
import com.liquidnet.service.platform.param.ticketSystem.STInsertFieldParam;
import com.liquidnet.service.platform.param.ticketSystem.STInsertPerformanceParam;
import com.liquidnet.service.platform.service.ticketSystem.ITicketSystemService;
import com.liquidnet.service.platform.vo.ticketSystem.*;
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.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 票务对接平台 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-11
 */
@Service
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");
            MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
            params.add("appId", appId);
            params.add("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");
        ResponseListVo<List<STPTListVo>> response =
                JsonUtils.fromJson(HttpUtil.get(ticketSystemUrl + "/standard/performance/type/list?accessToken=" + accessToken, null, headers),
                        new TypeReference<ResponseListVo<List<STPTListVo>>>() {
                        });
        return response.getData().getDataList();
    }

    @Override
    public List<STFieldListVo> getFieldList(String accessToken, STFieldListParam fieldListParam) {
        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("provinceId", fieldListParam.getProvinceId() + "");
        params.add("cityId", fieldListParam.getCityId() + "");
        params.add("districtId", fieldListParam.getDistrictId() + "");
        params.add("pageNo", fieldListParam.getPageNo().toString());
        params.add("pageSize", fieldListParam.getPageSize().toString());
        params.add("venueName", fieldListParam.getVenueName());
        ResponseDataVo<List<STFieldListVo>> response =
                JsonUtils.fromJson(HttpUtil.postRaw(ticketSystemUrl + "/standard/venue/list", JSON.toJSONString(params), headers),
                        new TypeReference<ResponseDataVo<List<STFieldListVo>>>() {
                        });
        return response.getData();
    }

    @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, String performanceId, String performanceName, String performanceDesc, Integer typeId, String posterUrl, String sponsor, String performer, String approval) {
        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", performanceId);
        params.add("performanceName", performanceName);
        params.add("approval", approval);
        params.add("typeId", typeId.toString());
        params.add("posterUrl", posterUrl);
        params.add("performanceDesc", performanceDesc);
        params.add("sponsor", sponsor);
        params.add("performer", performer);
        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, String sessionId, String sessionCode, String sessionName, LocalDateTime sessionStartTime,
                               LocalDateTime sessionEndTime, String hallCode, Integer hasSeat, String performanceId, Integer sessionStatus,
                               Integer tag, String seatingChart) {
        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", sessionId);
        params.add("sessionCode", sessionCode);
        params.add("sessionName", sessionName);
        params.add("sessionStartTime", DateUtil.Formatter.yyyyMMddHHmmss.format(sessionStartTime));
        params.add("sessionEndTime", DateUtil.Formatter.yyyyMMddHHmmss.format(sessionEndTime));
        params.add("hallCode", hallCode);
        params.add("hasSeat", hasSeat.toString());
        params.add("performanceId", performanceId);
        params.add("sessionStatus", sessionStatus.toString());
        params.add("tag", tag.toString());
        params.add("seatingChart", seatingChart);
        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, String sessionCode, List<TicketPriceVo> priceList) {
        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", sessionCode);
        params.add("priceList", JSON.toJSONString(priceList));
        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, String performanceId, String sessionCode, String priceId) {
        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", performanceId);
        params.add("sessionCode", sessionCode);
        params.add("priceId", priceId);
        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, String performanceId, String sessionId, String sessionCode, String priceId, List<TicketVo> 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("performanceId", performanceId);
        params.add("sessionId", sessionId);
        params.add("sessionCode", sessionCode);
        params.add("priceId", priceId);
        params.add("ticketList", JSON.toJSONString(ticketList));
        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, String performanceId, String sessionCode, String priceId, String ticketId) {
        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", performanceId);
        params.add("sessionCode", sessionCode);
        params.add("priceId", priceId);
        params.add("ticketId", ticketId);
        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, String orderId, LocalDateTime orderTime, Integer channelType, String channelName, Integer ticketNum,
                               long totalAmount, Integer ticketType, Integer ticketMode, Integer authMode, List<OrderVo> ticketOrderList) {
        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", orderId);
        params.add("orderTime", DateUtil.Formatter.yyyyMMddHHmmss.format(orderTime));
        params.add("channelType", channelType.toString());
        params.add("channelName", channelName);
        params.add("ticketNum", ticketNum.toString());
        params.add("totalAmount", totalAmount + "");
        params.add("ticketType", ticketType.toString());
        params.add("ticketMode", ticketMode.toString());
        params.add("authMode", authMode.toString());
        params.add("ticketOrderList", JSON.toJSONString(ticketOrderList));
        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, String refundOrderId, String orderId, String reason, LocalDateTime refundOrderTime, List<RefundOrderVo> ticketOrderList) {
        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", refundOrderId);
        params.add("orderId", orderId);
        params.add("reason", reason);
        params.add("refundOrderTime", DateUtil.Formatter.yyyyMMddHHmmss.format(refundOrderTime));
        params.add("ticketOrderList", JSON.toJSONString(ticketOrderList));
        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();
    }
}
