package top.baogutang.admin.schedule;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import top.baogutang.admin.domain.IphoneProductDto;
import top.baogutang.admin.utils.DingTalkMsgPushUtils;
import top.baogutang.admin.utils.IphoneProductParserUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 苹果库存监控
 * @author: nikooh
 * @date: 2023/10/13 : 15:12
 */
@Slf4j
@Component
@RefreshScope
public class AppleInventoryScheduleHandler extends IJobHandler {

    @Value("${baogutang.apple.country_code:cn}")
    private String countryCode;

    @Value("${baogutang.apple.device_code:15-pro}")
    private String deviceCode;

    @Value("${baogutang.apple.location:'上海 上海 闵行区'}")
    private String location;

    @Value("${baogutang.apple.switch:true}")
    private Boolean appleInventoryMonitorSwitch;

    //    @Value("${baogutang.apple.storeList}")
    private List<String> storeList = new ArrayList<>();

    @Resource
    private IphoneProductParserUtils iphoneProductParserUtils;

    @Resource
    private DingTalkMsgPushUtils dingTalkMsgPushUtils;

    private void doMonitor(IphoneProductDto product) {


        Map<String, Object> queryMap = new HashMap<>(5);
        queryMap.put("pl", "true");
        queryMap.put("mts.0", "regular");
        queryMap.put("parts.0", product.getModel());
        queryMap.put("location", location);

        String baseUrl = String.format("https://www.apple.com.%s", countryCode);
        Map<String, List<String>> headers = buildHeaders(baseUrl, deviceCode, product.getModel());
        String url = baseUrl + "/shop/fulfillment-messages?" + URLUtil.buildQuery(queryMap, CharsetUtil.CHARSET_UTF_8);
        try {
            HttpResponse httpResponse = HttpRequest.get(url)
                    .header(headers)
                    .execute();
            if (!httpResponse.isOk()) {
                log.warn(">>>>>>>>>>请求可能过于频繁，请稍后再试～<<<<<<<<<<");
                return;
            }
            JSONObject responseJsonObject = JSON.parseObject(httpResponse.body());
            JSONObject pickupMessage = responseJsonObject.getJSONObject("body").getJSONObject("content").getJSONObject("pickupMessage");
            JSONArray stores = pickupMessage.getJSONArray("stores");
            if (stores == null) {
                log.debug(pickupMessage.toString());
                return;
            }
            if (stores.isEmpty()) {
                log.info("您所在的 {} 附近没有Apple直营店，请检查您的地址是否正确", location);
                return;
            }
            StringBuilder pushContentBuilder = new StringBuilder();
            List<String> availableStoreNameList = stores.stream()
                    .filter(store -> filterStore((JSONObject) store))
                    .filter(k -> judgingStoreInventory((JSONObject) k, product.getModel()))
                    .map(store -> ((JSONObject) store).getString("storeName")
                            .trim())
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(availableStoreNameList)) {
                return;
            }
            JSONObject storeJson = (JSONObject) stores.get(0);
            JSONObject partsAvailability = storeJson.getJSONObject("partsAvailability");
            String deviceName = partsAvailability.getJSONObject(product.getModel()).getJSONObject("messageTypes").getJSONObject("regular").getString("storePickupProductTitle");
            pushContentBuilder.append("**")
                    .append(deviceName)
                    .append("**")
                    .append("今天可取货:")
                    .append("<br />");
            availableStoreNameList.forEach(availableStoreName ->
                    pushContentBuilder.append("**")
                            .append(availableStoreName)
                            .append("** <br />"));
            dingTalkMsgPushUtils.robotMarkdownMsgPush("苹果商店监控", "前往购买", "https://www.apple.com/" + countryCode + "/shop/buy-iphone/iphone-" + deviceCode, pushContentBuilder.toString());
        } catch (Exception e) {
            log.error("AppleMonitor error", e);
        }
    }

    /**
     * build request headers
     *
     * @param baseUrl     base country url
     * @param productCode product code
     * @return headers
     */
    private Map<String, List<String>> buildHeaders(String baseUrl, String deviceCode, String productCode) {

        ArrayList<String> referer = new ArrayList<>();
        referer.add(baseUrl + "/shop/buy-iphone/" + deviceCode + "/" + productCode);

        Map<String, List<String>> headers = new HashMap<>(10);
        headers.put(Header.REFERER.getValue(), referer);

        return headers;
    }

    private boolean filterStore(JSONObject storeInfo) {
        if (CollectionUtils.isEmpty(storeList)) {
            return Boolean.TRUE;
        }
        String storeName = storeInfo.getString("storeName");
        return storeList.stream()
                .anyMatch(k -> storeName.contains(k) || k.contains(storeName));
    }

    /**
     * check store inventory
     *
     * @param storeJson   store json
     * @param productCode product code
     * @return boolean
     */
    private boolean judgingStoreInventory(JSONObject storeJson, String productCode) {
        JSONObject partsAvailability = storeJson.getJSONObject("partsAvailability");
        String status = partsAvailability.getJSONObject(productCode).getString("pickupDisplay");
        return "available".equals(status);

    }

    /**
     * build pickup information
     *
     * @param retailStore retailStore
     * @return pickup message
     */
    private String buildPickupInformation(JSONObject retailStore) {
        String distanceWithUnit = retailStore.getString("distanceWithUnit");
        String twoLineAddress = retailStore.getJSONObject("address").getString("twoLineAddress");
        String daytimePhone = retailStore.getJSONObject("address").getString("daytimePhone");
        String messageTemplate = "\n取货地址:{},电话:{},距离{}:{}";
        return CharSequenceUtil.format(messageTemplate, twoLineAddress.replace("\n", " "), daytimePhone, location, distanceWithUnit);
    }

    @Override
    @XxlJob("appleInventoryScheduleHandler")
    public ReturnT<String> execute(String params) throws Exception {
        if (!Boolean.TRUE.equals(appleInventoryMonitorSwitch)) {
            log.info(">>>>>>>>>>apple inventory monitor switch closed!<<<<<<<<<<");
            return ReturnT.SUCCESS;
        }
        // 获取设备信息
        List<IphoneProductDto> products = iphoneProductParserUtils.getProducts(deviceCode, countryCode);
        //监视机型型号
        products.forEach(product -> {
            this.doMonitor(product);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                log.error(">>>>>>>>>>apple inventory monitor error:{}<<<<<<<<<<", e.getMessage(), e);
            }
        });
        return ReturnT.SUCCESS;
    }
}
