package com.backendsys.controller.B2c;

import com.backendsys.aspect.HttpRequestAspect;
import com.backendsys.aspect.QueryNullCheck;
import com.backendsys.aspect.QueryNullCheckAspect;
import com.backendsys.entity.B2c.B2cOrderDTO;
import com.backendsys.entity.PageDTO;
import com.backendsys.service.B2c.B2cGoodSpecSkuService;
import com.backendsys.service.B2c.B2cMemberService;
import com.backendsys.service.B2c.B2cOrderService;
import com.backendsys.service.B2c.B2cShoppingCartService;
import com.backendsys.utils.CommonUtil;
import com.backendsys.utils.response.Result;

import com.backendsys.utils.response.ResultEnum;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;

/**
 * 订单
 */
@Validated
@RestController
public class B2cOrderController {

    @Autowired
    private B2cMemberService b2cMemberService;
    @Autowired
    private B2cOrderService b2cOrderService;
    @Autowired
    private B2cGoodSpecSkuService b2cGoodSpecSkuService;
    @Autowired
    private B2cShoppingCartService b2cShoppingCartService;

    @PreAuthorize("@sr.hasPermission('6.3')")
    @GetMapping("/api/b2c/order/getOrder")
    public Result getOrder(@Validated PageDTO pageDTO, @Validated B2cOrderDTO b2cOrderDTO) {
        return Result.success(b2cOrderService.queryOrderList(pageDTO.getPage_num(), pageDTO.getPage_size(), b2cOrderDTO));
    }
    
    @PreAuthorize("@sr.hasPermission('6.3.1')")
    @QueryNullCheck(serviceClass = B2cOrderService.class, serviceMethod = "queryOrderDetail", argField = "order_id", message = "订单不存在")
    @GetMapping("/api/b2c/order/getOrderDetail")
    public Result getOrderDetail(@Validated(B2cOrderDTO.Detail.class) B2cOrderDTO b2cOrderDTO) {
        return Result.success(QueryNullCheckAspect.getQueryResult());
    }

    @PreAuthorize("@sr.hasPermission('6.3.3')")
    @QueryNullCheck(serviceClass = B2cOrderService.class, serviceMethod = "queryOrderDetail", argField = "order_id", message = "订单不存在")
    @PutMapping("/api/b2c/order/updateOrder")
    public Result updateOrder(@Validated(B2cOrderDTO.Update.class) @RequestBody B2cOrderDTO b2cOrderDTO) {
        return Result.success(b2cOrderService.updateOrder(b2cOrderDTO), "更新成功");
    }


    @Autowired
    private HttpRequestAspect httpRequestAspect;

//    /**
//     * 生成一个随机订单编码 (OR-时间戳-3位随机数)
//     */
//    private String generateRandomOrderCode(String timestamp) {
//        Random random = new Random();
//        String randomNumber = String.format("%03d", random.nextInt(1000));
//        String orderCode = "OR-" + timestamp + "-" + randomNumber;
//        return orderCode;
//    }

    /**
     * 计算最终支付金额
     */
    private BigDecimal computeTotalPrice() {
        return BigDecimal.valueOf(1);
    }


    /**
     * [格式化] 规格字符串
     */
    private String filterSpecString(List<Map<String, Object>> specs) {
        String specString = "";
        int lastIndex = specs.size() - 1;
        for (int i = 0; i < specs.size(); i++) {
            Map<String, Object> spec = specs.get(i);
            specString += spec.get("name") + ":" + spec.get("value");
            if (i != lastIndex) specString += ", ";
        }
        return specString;
    }
    /**
     * [格式化] 获得规格信息 (spec_ids: [1, 2] 转为 specs: [{ id: 1, name: "颜色", value: "红" }])
     * - 使用关联查询，获得 { spec_names, spec_values }
     * - 再按索引顺序进行格式化
     * - 删除多余属性
     */
    private void addSpecToList(List<Map<String, Object>> goodSpecSkuList) {
        for (Map<String, Object> sku : goodSpecSkuList) {
            List<Map<String, Object>> specs = new ArrayList<>();
            String[] spec_ids = ((String) sku.get("spec_ids")).split(",");
            String[] spec_names = ((String) sku.get("spec_names")).split(",");
            String[] spec_values = ((String) sku.get("spec_values")).split(",");
            for (int i = 0; i < spec_names.length; i++) {
                Map<String, Object> spec = new LinkedHashMap<>();
                spec.put("id", Integer.parseInt(spec_ids[i]));
                spec.put("name", spec_names[i]);
                spec.put("value", spec_values[i]);
                specs.add(spec);
            }
            // [格式化] 规格字符串
            String specString = filterSpecString(specs);
            sku.put("specs_string", specString);
            sku.put("specs", specs);
            //
            sku.remove("spec_names");
            sku.remove("spec_values");
            sku.remove("is_stock");
        }
    }

    /**
     * [格式化] 将请求的数量 { quantity } 属性赋给查询结果
     */
    private void addQuantity(List<Map<String, Object>> requestSkuList, List<Map<String, Object>> goodSpecSkuList) {
        for (Map<String, Object> reqSku : requestSkuList) {
            Integer quantity = (Integer) reqSku.get("quantity");
            for (Map<String, Object> sku : goodSpecSkuList) {
                if (((Integer) reqSku.get("id")).longValue() == (Long) sku.get("id")) {
                    sku.put("quantity", quantity);
                }
            }
        }
    }

    /**
     * 确认订单 (在订单确认页展示商品信息、价格、数量等细节，或选择优惠券，生成订单支付页前的确认信息)
     * @param { sku_ids, coupon_id }
     */
    @PreAuthorize("@ss.isMember")
    @PostMapping("/api/front/b2c/order/generateConfirmOrder")
    public Result confirmOrder(@Validated(B2cOrderDTO.Confirm.class) @RequestBody B2cOrderDTO b2cOrderDTO) {

        Map<String, Object> data = new LinkedHashMap<>();

        // [获得] 商品及规格信息
        List<Map<String, Object>> requestSkuList = b2cOrderDTO.getSku();

        // [获得] 批量 商品/规格信息
        Long[] requestSkuIds = requestSkuList.stream().map(item -> ((Integer) item.get("id")).longValue()).toArray(Long[]::new);
        List<Map<String, Object>> querySpecSkuList = b2cGoodSpecSkuService.queryGoodSpecSkuBatch(requestSkuIds);

        // [格式化] 遍历，获得规格信息 (spec_ids: [1, 2] 转为 specs: [{ id: 1, name: "颜色", value: "红" }])
        addSpecToList(querySpecSkuList);

        // [格式化] 将请求的数量 { quantity } 属性赋给查询结果
        addQuantity(requestSkuList, querySpecSkuList);

        // [判断] 购买数量 不大于 商品库存，否则报错
        for (Map<String, Object> sku : querySpecSkuList) {
            if ((Integer) sku.get("quantity") > (Integer) sku.get("stock")) {
//                List<Map<String, Object>> specs = (List<Map<String, Object>>) sku.get("specs");
                // [格式化] 规格字符串
                return Result.error(ResultEnum.INTERNAL_ERROR.getCode(), "「" + sku.get("good_name") + "」「" + sku.get("specs_string") + "」库存不足", sku);
            }
        }
        // [赋值] 返回规格查询结果 { good_spec_sku } (包含购买数量)
        data.put("good_spec_sku", querySpecSkuList);

        // .. 返回优惠券信息 (自己的) (符合商品条件的)
        // .. 如果有优惠券ID { coupon_id }，则在此处获取，并一起在此处计算 总价

        // [赋值] 根据数量和单价，计算获得 总价 { total_price }
        BigDecimal totalPrice = new BigDecimal(0);
        for (Map<String, Object> sku : querySpecSkuList) {
            BigDecimal price = (BigDecimal) sku.get("price");
            Integer quantity = (Integer) sku.get("quantity");
            totalPrice = totalPrice.add(price.multiply(new BigDecimal(quantity)));
        }
        data.put("total_price", totalPrice);


        // [加密] 将SKU信息加密回传 (确认订单-加密 / 预付下单-解密)
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            String dataString = objectMapper.writeValueAsString(data);
            System.out.println(dataString);
            data.put("encrypted", encoder.encode(dataString));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }


        return Result.success(data);
    }

    /**
     * 创建订单
     */
    @PreAuthorize("@ss.isMember")
    @PostMapping("/api/front/b2c/order/createOrder")
    public Result createOrder(@Validated(B2cOrderDTO.Create.class) @RequestBody B2cOrderDTO b2cOrderDTO) {

        System.out.println(b2cOrderDTO.getEncrypted());

        b2cOrderDTO.setMember_id(httpRequestAspect.getMemberId());

        // 生成当前的时间戳
        LocalDateTime now = LocalDateTime.now();
        String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // ---- 1.生成一个随机订单编码 (OR-时间戳-3位随机数) -----------------------------------------------------
        b2cOrderDTO.setOrder_code(CommonUtil.generateRandomOrderCode("OR"));

        // ---- 2.获得当前登录的 { member_id }，再调用 info 接口获得 { member_open_id } -------------------------
        Long member_id = b2cOrderDTO.getMember_id();
        Map<String, Object> memberInfo = b2cMemberService.queryMemberDetail(member_id);
        b2cOrderDTO.setMember_open_id((String) memberInfo.get("open_id"));

        // ---- 3.预支付订单下单 (第三方) (待做) ---------------------------------------------------------------
        // [判断] 支付方式：
        String payMethod = b2cOrderDTO.getPay_method();
        // [微信支付]
        if (payMethod == "WeChatPay") {}
        // [支付宝支付]
        if (payMethod == "AliPay") {}
        // [获得] 从第三方支付接口获得预支付订单码 (临时)
        Random random = new Random();
        String ran = String.format("%03d", random.nextInt(1000));
        String prepay_id = "PAY-" + timestamp + "-" + ran;
        b2cOrderDTO.setPrepay_id(prepay_id);

        // ---- 4.来源 (待做) -------------------------------------------------------------------------------
        // (应该可以不用做来源，不论是从购物车还是从规格，都要传递SKU进入订单确认页的)

        //// 订单来源 (1从购物车, 2从规格 (spec_sku_id) )
        //Integer orderSource = b2cOrderDTO.getOrder_source();
        //// [从购物车]
        //if (orderSource == 1) {
        //    // .. 购物车下单
        //    // [获得] 购物车信息 (自己的)
        //    Map<String, Object> shoppingCart = b2cShoppingCartService.queryShoppingCartList();
        //    System.out.println(shoppingCart);
        //}
        //// [从规格]
        //if (orderSource == 2) {
        //    Long specSkuId = b2cOrderDTO.getSpec_sku_id();
        //    if (specSkuId == null) {
        //        return Result.error(ResultEnum.INTERNAL_ERROR.getCode(), "规格ID不能为空");
        //    } else {
        //        // .. 规格下单
        //    }
        //}

        // ---- 5.计算金额 -------------------------------------------------------------------------------
        b2cOrderDTO.setFinal_total_price(computeTotalPrice());

        return Result.success(b2cOrderService.insertOrder(b2cOrderDTO), "创建成功");
    }
}
