package com.ruoyi.app.order;

/**
 * 订单商家操作
 */

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.app.order.dto.OrderCreatItem;
import com.ruoyi.app.order.dto.OrderCreateInput;
import com.ruoyi.app.order.dto.OrderPushBodyDto;
import com.ruoyi.app.utils.PayPush;
import com.ruoyi.app.utils.event.PushEventService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.Auth;
import com.ruoyi.system.utils.JwtUtil;
import com.ruoyi.system.domain.dto.InvalidInvoiceDto;
import com.ruoyi.system.utils.OrderLogHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * posorderController
 *
 * @author ruoyi
 * @date 2023-05-23
 */
@RestController
@RequestMapping("/system/orderShOprate")
public class PosOrderShOprateController extends BaseController {
    @Autowired
    private IPosOrderService posOrderService;
    @Autowired
    private IInfoUserService infoUserService;
    @Autowired
    private PushEventService pushEventService;
    @Autowired
    private OrderLogHelper orderLogHelper;
    @Autowired
    private IPosStoreService posStoreService;
    @Autowired  //经营时间
    private IOperatingHoursService operatingHoursService;
    @Autowired
    private IOrderParentService orderParentService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderInvoiceService orderInvoiceService;



    /**
     * 商家端查询订单发票（状态/发票号/凭证）
     */

    @GetMapping("/getInvoice")
    @Auth
    @Anonymous
    public AjaxResult getInvoice(@RequestHeader String token, @RequestParam Long orderId) {
        Long userId = Long.valueOf(new JwtUtil().getusid(token));
        return AjaxResult.success(orderInvoiceService.getInvoiceForMerchant(orderId, userId));
    }

    /**
     * 商家端作废订单发票（仅已开，调 ezPay invoice_invalid）。入参可选 {invalidReason}
     */

    @PutMapping("/invalidInvoice/{orderId}")
    @Auth
    @Anonymous
    public AjaxResult invalidInvoice(@RequestHeader String token, @PathVariable Long orderId,
                                     @RequestBody(required = false) InvalidInvoiceDto dto) {
        Long userId = Long.valueOf(new JwtUtil().getusid(token));
        String reason = dto == null ? null : dto.getInvalidReason();
        return toAjax(orderInvoiceService.invalidForMerchant(orderId, reason, userId));
    }

    /**
     * 商家端下单
     */
    @PostMapping("/createOrder")
    @Auth
    @Anonymous
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult createOrder(@RequestHeader String token, @RequestBody OrderCreateInput input)
    {
        JwtUtil jwtUtil = new JwtUtil();
        String id = jwtUtil.getusid(token);
        String shdz=null;
        createOrderParent(input,Long.valueOf(id),shdz);
        createOrderChild(input,Long.valueOf(id),Long.valueOf(id),shdz);

        OrderParent result = orderParentService.getOne(new LambdaQueryWrapper<OrderParent>().eq(OrderParent::getDdId, input.getDdId().toString()));
        System.out.println("创建返回信息："+result);
        return super.success(result);
    }

    //创建父订单
    private void createOrderParent(OrderCreateInput input,Long UserId,String shdz){
        OrderParent orderParent = new OrderParent();
        orderParent.setUserId(UserId);
        orderParent.setOrderStatus(0L);
        orderParent.setTotalAmount(input.getTotalAmount());
        orderParent.setActualPayAmount(input.getActualPayAmount());
        orderParent.setPaymentMethod(input.getPaymentMethod());
//        orderParent.setPaymentTime(new Date());
        orderParent.setCreateTime(new Date());
//        orderParent.setUpdateTime(new Date());
        orderParent.setDdId(input.getDdId().toString());
        orderParent.setTableId(input.getTableId());
        orderParent.setShdzId(input.getShdzId());
        orderParent.setShAddress(shdz);
        orderParent.setType(input.getType());
        orderParent.setRemarks(input.getRemarks());
        orderParentService.save(orderParent);
    }
    //创建子订单
    private void createOrderChild(OrderCreateInput input,Long orderParentId,Long userId,String shdz){
        // 检查items是否为空
        if (input.getItems() == null || input.getItems().isEmpty()) {
            throw new ServiceException(MessageUtils.message("订单商品不能为空"));
        }
        String ddId = input.getDdId().toString();
        List<Long> mdIdList = input.getItems().stream().map(OrderCreatItem::getMdId).collect(Collectors.toList());
        // 将Long类型的门店ID转换为Integer类型用于查询（因为PosStore.getId()返回Integer）
        List<Integer> mdIdIntegerList = mdIdList.stream().map(Long::intValue).collect(Collectors.toList());
        List<PosStore> storeList = posStoreService.list(new LambdaQueryWrapper<PosStore>().in(PosStore::getId, mdIdIntegerList));
        LambdaQueryWrapper<OperatingHours> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(OperatingHours::getMdId, mdIdList);
        List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
        boolean isMultiStore = input.getItems().size() > 1;
        // 循环items，为每个item创建一条PosOrder
        int index = 0;
        for (OrderCreatItem item : input.getItems()) {
            index++;
            // 单店铺：子订单号与父订单一致；多店铺：子订单号追加序号
            String subddId = isMultiStore ? ddId + String.format("%03d", index) : ddId;
            PosOrder posOrder = new PosOrder();
            posOrder.setIsDisplay(true);
            posOrder.setDisplayTime(new Date());
            posOrder.setShdzId(input.getShdzId());
            // 设置子订单的基本信息
            posOrder.setDdId(subddId);
            posOrder.setParentDdId(input.getDdId().toString()); // 设置父订单ID
            posOrder.setCretim(new Date());
            posOrder.setState(1L); // 初始状态
            // 根据item设置订单信息
            posOrder.setShId(item.getShId());
            posOrder.setMdId(item.getMdId());
            posOrder.setShdzId(input.getShdzId());
            posOrder.setUserId(userId);
            posOrder.setAmount(item.getAmount());
            posOrder.setRemarks(item.getRemarks());
            posOrder.setType(item.getType());
            posOrder.setDelryTime(item.getDelryTime());
            posOrder.setFood(JSON.toJSONString(item.getFood()));
            // 设置支付相关信息（从父订单继承）
            posOrder.setPayType(input.getPaymentMethod());
            //设置桌号（从父订单继承）
            posOrder.setTableId(input.getTableId());
            posOrder.setTableNo(input.getTableNo());
            posOrder.setLogo(item.getLogo());
            posOrder.setPosName(item.getPosName());
            posOrder.setJvli(item.getJvli());
            posOrder.setFreight(item.getFreight());
            posOrder.setShdzId(input.getShdzId());
            posOrder.setShAddress(shdz);
            posOrder.setFoodAmount(item.getFoodAmount());
            Optional<PosStore> storeOptional = storeList.stream()
                    .filter(x -> item.getMdId().equals(Long.valueOf(x.getId())))
                    .findFirst();
            if (storeOptional.isEmpty()) {
                throw new ServiceException(MessageUtils.message("no.mendian.not.exist"));
            }
            PosStore store = storeOptional.get();
            posOrder.setLongitude(store.getLongitude());
            posOrder.setLatitude(store.getLatitude());
            //设置订单分类
            storeList.stream().filter(s -> Long.valueOf(s.getId()).equals(item.getMdId())).findFirst().ifPresent(st -> {
                posOrder.setOrderCategory(String.valueOf(st.getType()));
            });
            setPickUpNum(posOrder);
            posOrderService.save(posOrder);
        }
    }

    //生成取餐码，根据门店id,当天取餐码从1开始累加
    private void setPickUpNum(PosOrder order) {
        if (order == null || order.getMdId() == null) {
            return;
        }
        try {
            // 获取当前日期，格式为 yyyy-MM-dd
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String today = dateFormat.format(new Date());

            // 查询当天该门店的最大取餐码
            LambdaQueryWrapper<PosOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(PosOrder::getMdId, order.getMdId());
            queryWrapper.like(PosOrder::getCretim, today);
            queryWrapper.orderByDesc(PosOrder::getPickUpNum);
            queryWrapper.last("LIMIT 1");

            PosOrder lastOrder = posOrderService.getOne(queryWrapper);
            long nextNum = 1L;
            if (lastOrder != null && lastOrder.getPickUpNum() != null) {
                // 直接使用Long类型的取餐码
                nextNum = lastOrder.getPickUpNum() + 1;
            }
            // 生成新的取餐码：直接使用Long数字
            order.setPickUpNum(nextNum);
            logger.info("生成取餐码成功：门店ID={}, 取餐码={}", order.getMdId(), nextNum);

        } catch (Exception e) {
            logger.error("生成取餐码失败：门店ID={}, 错误信息={}", order.getMdId(), e.getMessage(), e);
            // 生成失败时使用时间戳作为备用方案
            Long fallbackPickUpNum = System.currentTimeMillis() % 10000;
            order.setPickUpNum(fallbackPickUpNum);
        }
    }


    /**
     * 商家接单：state 从 0 改为 1
     */
    @Anonymous
    @Auth
    @GetMapping("/acceptOrder")
    public AjaxResult acceptOrder(@RequestHeader String token, @RequestParam Long id) {
        PosOrder order = posOrderService.getOne(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getId, id));
        if (order == null || order.getState() == null || order.getState() != 0L) {
            throw new ServiceException("订单不存在或状态不允许接单");
        }
        PosOrder update = new PosOrder();
        update.setId(order.getId());
        update.setState(1L);
        posOrderService.saveOrUpdate(update);
        InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
        String shName = shUser != null ? shUser.getNickName() : "";
        orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已接单");
        return AjaxResult.success();
    }

    /**
     * 商家出餐：state 从 1 改为 2
     * 外送订单额外设置 deliveryStatus=0（等待骑手接单）
     */
    @Anonymous
    @Auth
    @GetMapping("/dispatchOrder")
    public AjaxResult dispatchOrder(@RequestHeader String token, @RequestParam Long id) {
        PosOrder order = posOrderService.getOne(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getId, id));
        if (order == null || order.getState() == null || order.getState() != 1L) {
            throw new ServiceException("订单不存在或状态不允许出餐");
        }
        PosOrder update = new PosOrder();
        update.setId(order.getId());
        update.setState(2L);
        // 外送订单：设置 deliveryStatus=0 等待骑手接单
        if (order.getType() != null && order.getType() == 0L) {
            update.setDeliveryStatus(0L);
        }
        posOrderService.saveOrUpdate(update);
        InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
        String shName = shUser != null ? shUser.getNickName() : "";
        orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已出餐");
        // 出餐推送
        chuCan(order, update);
        return AjaxResult.success();
    }

    /**
     * 商家完成（自取/堂食）：state 从 2 改为 3，payStatus 从 0 改为 1
     */
    @Anonymous
    @Auth
    @GetMapping("/completeOrder")
    public AjaxResult completeOrder(@RequestHeader String token, @RequestParam Long id) {
        PosOrder order = posOrderService.getOne(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getId, id));
        if (order == null || order.getState() == null || order.getState() != 2L) {
            throw new ServiceException("订单不存在或状态不允许完成");
        }
        // 仅限自取(type=1)或堂食(type=2)
        if (order.getType() == null || (order.getType() != 1L && order.getType() != 2L)) {
            throw new ServiceException("仅自取和堂食订单支持此操作");
        }
        PosOrder update = new PosOrder();
        update.setId(order.getId());
        update.setState(3L);
        update.setPayStatus(1L);
        posOrderService.saveOrUpdate(update);
        InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
        String shName = shUser != null ? shUser.getNickName() : "";
        orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已完成订单");
        // 商家完成订单时生成商家账单
        PosOrder fullOrder = posOrderService.getById(order.getId());
        orderService.setSanghuBilling(fullOrder);
        return AjaxResult.success();
    }

    /**
     * 商家取消订单：校验 state IN (0,1)，设 state=4
     */
    @Anonymous
    @Auth
    @GetMapping("/cancelOrder")
    public AjaxResult cancelOrder(@RequestHeader String token, @RequestParam Long id) {
        PosOrder order = posOrderService.getOne(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getId, id));
        if (order == null || order.getState() == null) {
            throw new ServiceException("订单不存在");
        }
        if (order.getState() != 0L && order.getState() != 1L) {
            throw new ServiceException("当前状态不允许取消");
        }
        PosOrder update = new PosOrder();
        update.setId(order.getId());
        update.setState(4L);
        posOrderService.saveOrUpdate(update);
        InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
        String shName = shUser != null ? shUser.getNickName() : "";
        orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "取消订单");
        return AjaxResult.success();
    }

    /**
     * 商家出餐推送：给用户和骑手推送通知
     */
    public void chuCan(PosOrder oldOrder, PosOrder posOrder) {
        List<Long> ids = new ArrayList<>();
        ids.add(oldOrder.getUserId());
        if (oldOrder.getQsId() != null) {
            ids.add(oldOrder.getQsId());
        }
        List<InfoUser> users = infoUserService.list(new LambdaQueryWrapper<InfoUser>().in(InfoUser::getUserId, ids));
        Optional<InfoUser> user = users.stream().filter(x -> "0".equals(x.getUserType())).findFirst();
        Optional<InfoUser> qsUser = users.stream().filter(x -> "2".equals(x.getUserType())).findFirst();

        String title = "no.message.push.message";
        String content = "no.message.push.merchant.ready.content";
        Long stateVal = posOrder.getState() != null ? posOrder.getState() : oldOrder.getState();
        String stateStr = stateVal != null ? String.valueOf(stateVal) : "2";
        String body = OrderPushBodyDto.getJson(String.valueOf(oldOrder.getDdId()), stateStr);
        String ddId = String.valueOf(oldOrder.getDdId());

        if (user.isPresent()) {
            InfoUser u = user.get();
            PayPush push = new PayPush();
            Long uUserId = u.getUserId();
            String uCid = u.getCid();
            AsyncManager.me().execute(new TimerTask() {
                @Override
                public void run() {
                    PayPush.userPushHandleLocal(push, pushEventService, uUserId, uCid, title, content, body, "", ddId);
                }
            });
        }
        if (qsUser.isPresent()) {
            InfoUser qs = qsUser.get();
            if (!StringUtils.isEmpty(qs.getCid())) {
                PayPush push = new PayPush();
                Long qsUserId = qs.getUserId();
                String qsCid = qs.getCid();
                AsyncManager.me().execute(new TimerTask() {
                    @Override
                    public void run() {
                        PayPush.qsPushHandleLocal(push, pushEventService, qsUserId, qsCid, title, content, body, "", ddId);
                    }
                });
            }
        }
    }

    /**
     * 商家端订单列表（Tab分页）
     * ta
     */
    @Anonymous
    @Auth
    @GetMapping("/orderList")
    public AjaxResult orderList(@RequestHeader String token,
                                @RequestParam(defaultValue = "1") int page,
                                @RequestParam(defaultValue = "10") int size,
                                @RequestParam(required = false) String tab,
                                @RequestParam(required = false) Long mdId,
                                @RequestParam(required = false) String type) {
        JwtUtil jwtUtil = new JwtUtil();
        String userId = jwtUtil.getusid(token);
        // 查询当前用户信息
        InfoUser currentUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(userId)));
        if (currentUser == null) {
            throw new ServiceException("用户信息不存在");
        }

        LambdaQueryWrapper<PosOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(mdId!=null,PosOrder::getMdId,mdId);
        String userType = currentUser.getUserType();
        if ("3".equals(userType)) {
            // 夜市商家：shId等于用户id
            wrapper.eq(PosOrder::getShId, Long.valueOf(userId));
        } else if ("1".equals(userType)) {
            // 普通商家：shId等于用户id
            wrapper.eq(PosOrder::getShId, Long.valueOf(userId));
        } else {
            // 摊位商家：mdId等于用户表中的storeId
            if (currentUser.getStoreId() == null) {
                throw new ServiceException("摊位关联门店信息不存在");
            }
            wrapper.eq(PosOrder::getMdId, currentUser.getStoreId());
        }
        if (type != null && !type.isEmpty()) {
            wrapper.eq(PosOrder::getType, Long.valueOf(type));
        }
        switch (tab) {
            case "pending":
                wrapper.eq(PosOrder::getState, 0L)
                       .and(w -> w.eq(PosOrder::getPayStatus, 1L).or().in(PosOrder::getType, 1L, 2L));
                break;
            case "preparing":
                wrapper.eq(PosOrder::getState, 1L);
                break;
            case "ready":
                wrapper.eq(PosOrder::getState, 2L).eq(PosOrder::getAfterSaleStatus, 0L);
                break;
            case "completed":
                wrapper.eq(PosOrder::getState, 3L).eq(PosOrder::getAfterSaleStatus, 0L);
                break;
            case "cancelled":
                wrapper.eq(PosOrder::getState, 4L).eq(PosOrder::getAfterSaleStatus, 0L);
                break;
            case "refund":
                wrapper.gt(PosOrder::getAfterSaleStatus, 0L);
                break;
            default:
               break;
        }
        wrapper.orderByDesc(PosOrder::getCretim);

        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> pageParam =
                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page, size);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> result = posOrderService.page(pageParam, wrapper);

        return success(result);
    }

}
