package com.fjhx.victoriatourist.service.jd.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.fjhx.victoriatourist.entity.jd.po.JdOrder;
import com.fjhx.victoriatourist.entity.jd.po.JdOrderDetails;
import com.fjhx.victoriatourist.service.jd.JdApiService;
import com.fjhx.victoriatourist.service.jd.JdOrderDetailsService;
import com.fjhx.victoriatourist.service.jd.JdOrderService;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getdetailbyorderid.JOSDetailResultDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getdetailbyorderid.PurchaseAllocationDetailDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getpurchaseorderlist.JOSOrderResultDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getpurchaseorderlist.PurchaseOrderDto;
import com.jd.open.api.sdk.request.supplier.VcGetdetailbyorderidRequest;
import com.jd.open.api.sdk.request.supplier.VcGetpurchaseorderlistRequest;
import com.jd.open.api.sdk.response.supplier.VcGetdetailbyorderidResponse;
import com.jd.open.api.sdk.response.supplier.VcGetpurchaseorderlistResponse;
import com.ruoyi.framework.mybatis.holder.TenantHolder;
import com.ruoyi.system.utils.ConfigUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class JdApiServiceImpl implements JdApiService {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final String appKey = "ECCD5CE82A501C7E0D8BB41C030C447D";
    private static final String appSecret = "5b55c3f3eb874b0d8746ff28e7f91f64";

    @Autowired
    private JdOrderService jdOrderService;
    @Autowired
    private JdOrderDetailsService jdOrderDetailsService;

    /**
     * 获取AccessToken
     */
    @Override
    public void getAccessTokenByCode(String code) {
        if (ObjectUtil.isEmpty(code)) {
            log.error("获取AccessToken失败：code不能为空");
            return;
        }

        //获取AccessToken并存入数据库
        String path = "https://open-oauth.jd.com/oauth2/access_token?app_key=%s&app_secret=%s&grant_type=authorization_code&code=%s";
        path = String.format(path, appKey, appSecret, code);
        try {
            JSONObject responseJson = getJSON(new HttpGet(path));
            if (ObjectUtil.isNotEmpty(responseJson.getString("access_token")) && ObjectUtil.isNotEmpty(responseJson.getString("refresh_token"))) {
                log.info("成功获取AccessToken并保存" + responseJson);
                ConfigUtil.set("jd_token_json", responseJson.toString());
            } else {
                log.error("获取AccessToken失败：" + responseJson);
            }
        } catch (Exception e) {
            log.error("获取AccessToken出错：" + e.getMessage(), e);
        }
    }

    /**
     * 刷新Token
     */
    private void refreshToken() {
        String jdTokenJsonStr = ConfigUtil.get("jd_token_json");
        if (ObjectUtil.isEmpty(jdTokenJsonStr)) {
            log.error("jd_token_json为空无法刷新Token请检查");
            return;
        }
        JSONObject jdTokenJson = JSONObject.parseObject(jdTokenJsonStr);
        if (ObjectUtil.isEmpty(jdTokenJson.get("refresh_token"))) {
            log.error("refresh_token为空无法刷新Token请检查");
            return;
        }
        String path = "https://open-oauth.jd.com/oauth2/refresh_token?app_key=%s&app_secret=%s&grant_type=refresh_token&refresh_token=%s";
        path = String.format(path, appKey, appSecret, jdTokenJson.get("refresh_token"));
        try {
            JSONObject responseJson = getJSON(new HttpGet(path));
            if (ObjectUtil.isNotEmpty(responseJson.getString("access_token")) && ObjectUtil.isNotEmpty(responseJson.getString("refresh_token"))) {
                log.info("成功刷新AccessToken并保存" + responseJson);
                ConfigUtil.set("jd_token_json", responseJson.toString());
            } else {
                log.error("刷新AccessToken失败：" + responseJson);
            }
        } catch (Exception e) {
            log.error("刷新AccessToken出错：" + e.getMessage(), e);
        }
    }

    @DSTransactional
        //项目启动时运行一次
//    @PostConstruct
        // 每1分钟执行一次
//    @Scheduled(cron = "0 0/1 *  * * ? ")
    void orderSync() throws Exception {
        String tenantId = "prod".equals(SpringUtil.getActiveProfile()) ? "wdly" : "wdlytest";

        JSONObject jdTokenJson = JSONObject.parseObject(ConfigUtil.get("jd_token_json"));
        if (ObjectUtil.isEmpty(jdTokenJson)) {
            log.error("京东token详细为空请检查");
            return;
        }

        JdClient client = new DefaultJdClient("http://api.jd.com/routerjson", jdTokenJson.getString("access_token"), appKey, appSecret);

        //获取开始同步的时间
        Date startTime = sdf.parse("2023-11-01 00:00:00");
        TenantHolder.setIgnore(true);//忽略租户
        JdOrder lastJdOrder = jdOrderService.getOne(q -> q.isNotNull(JdOrder::getCreatedDate).orderByDesc(JdOrder::getCreatedDate));
        TenantHolder.clear();
        if (ObjectUtil.isNotEmpty(lastJdOrder)) {
            //将最后一个下单时间减1个小时设置为开始时间
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(lastJdOrder.getCreatedDate());
            calendar.add(Calendar.HOUR_OF_DAY, -1);

            startTime = calendar.getTime();
        }

        Date endTime = new Date();

        Integer recordCount = getJdOrderInfo(1, 1, startTime, endTime, client).getRecordCount();

        int pageSize = 50;
        int pageCount = (recordCount + pageSize - 1) / pageSize;

        List<PurchaseOrderDto> purchaseOrderList = new ArrayList<>();
        //数据返回订单是倒序反过来按正顺保存
        for (int i = pageCount; i > 0; i--) {
            JOSOrderResultDto josOrderResultDto = getJdOrderInfo(i, pageSize, startTime, endTime, client);
            purchaseOrderList.addAll(josOrderResultDto.getPurchaseOrderList());
        }

        //处理数据（过滤已存在的数据）
        List<Long> jdOrderIds = purchaseOrderList.stream().map(PurchaseOrderDto::getOrderId).collect(Collectors.toList());
        TenantHolder.setIgnore(true);//忽略租户
        //获取已同步的京东订单id
        List<Long> jdOrderIds1 = jdOrderService.listObject(JdOrder::getOrderId, q -> q.in(JdOrder::getOrderId, jdOrderIds));
        TenantHolder.clear();

        //过滤出未同步的数据
        List<PurchaseOrderDto> purchaseOrderListFilter = purchaseOrderList.stream().filter(item -> !jdOrderIds1.contains(item.getOrderId())).collect(Collectors.toList());

        //转为系统自己的实体类
        List<JdOrder> jdOrderList = BeanUtil.copyToList(purchaseOrderListFilter, JdOrder.class);
        //赋值租户id
        jdOrderList.forEach(item -> item.setTenantId(tenantId));
        //将数据存储到库
        TenantHolder.setIgnore(true);//忽略租户
        jdOrderService.saveBatch(jdOrderList);
        TenantHolder.clear();

        //获取明细
        List<JdOrderDetails> jdOrderDetailsList = new ArrayList<>();
        for (JdOrder jdOrder : jdOrderList) {
            VcGetdetailbyorderidRequest request = new VcGetdetailbyorderidRequest();
            request.setOrderId(jdOrder.getOrderId());
            request.setIsPage(false);
            VcGetdetailbyorderidResponse response = client.execute(request);

            JOSDetailResultDto josDetailResultDto = response.getJosDetailResultDto();
            List<PurchaseAllocationDetailDto> purchaseAllocationDetailList = josDetailResultDto.getPurchaseAllocationDetailList();

            List<JdOrderDetails> jdOrderDetails = BeanUtil.copyToList(purchaseAllocationDetailList, JdOrderDetails.class);
            jdOrderDetails.forEach(item -> item.setJdOrderId(jdOrder.getId()));

            jdOrderDetailsList.addAll(jdOrderDetails);
        }
        //赋值租户id
        jdOrderList.forEach(item -> item.setTenantId(tenantId));
        TenantHolder.setIgnore(true);//忽略租户
        jdOrderDetailsService.saveBatch(jdOrderDetailsList);
        TenantHolder.clear();
    }

    /**
     * 获取京东订单信息分页
     */
    private JOSOrderResultDto getJdOrderInfo(Integer pageIndex, Integer pageSize, Date startTime, Date endTime, JdClient client) throws Exception {
        VcGetpurchaseorderlistRequest request = new VcGetpurchaseorderlistRequest();
        request.setCreatedDateStart(startTime);
        request.setCreatedDateEnd(endTime);
        request.setPageIndex(pageIndex);
        request.setPageSize(pageSize);
        VcGetpurchaseorderlistResponse response = client.execute(request);
        return response.getJosOrderResultDto();
    }

    private static JSONObject getJSON(HttpRequestBase httpRequestBase) throws IOException {
        HttpClient client = HttpClients.createDefault();
        httpRequestBase.setConfig(RequestConfig.custom().setConnectTimeout(3000).build());
        HttpResponse response = client.execute(httpRequestBase);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity entity = response.getEntity();
        String responseStr = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8);
        if (statusCode != 200) {
            log.error("请求失败 {} {} {}", statusCode, httpRequestBase.getURI(), responseStr);
        }
        return JSONObject.parseObject(responseStr);
    }

    public static void main(String[] args) throws Exception {
        JdClient client = new DefaultJdClient("http://api.jd.com/routerjson", "a1f79f4670fd43a28fa2de02abd86f03ytfm", appKey, appSecret);


        {
            VcGetpurchaseorderlistRequest request = new VcGetpurchaseorderlistRequest();
            request.setCreatedDateStart(sdf.parse("2023-11-01 00:00:00"));
            request.setCreatedDateEnd(new Date());
            request.setPageIndex(1);
            request.setPageSize(10);
            VcGetpurchaseorderlistResponse response = client.execute(request);
            System.out.println(JSONObject.toJSONString(response));
        }


        {
            VcGetdetailbyorderidRequest request = new VcGetdetailbyorderidRequest();
            request.setOrderId(1490391996L);
            request.setIsPage(false);
            VcGetdetailbyorderidResponse response = client.execute(request);
            System.out.println(JSONObject.toJSONString(response));
        }

    }
}
