package com.jeeplus.hotelorder.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeeplus.hotelorder.dish.domain.HotelDish;
import com.jeeplus.hotelorder.dish.mapper.HotelDishMapper;
import com.jeeplus.hotelorder.dto.OrderCreateDTO;
import com.jeeplus.hotelorder.dto.OrderDashboardDTO;
import com.jeeplus.hotelorder.order.domain.HotelOrder;
import com.jeeplus.hotelorder.order.domain.HotelOrderItem;
import com.jeeplus.hotelorder.order.mapper.HotelOrderItemMapper;
import com.jeeplus.hotelorder.order.mapper.HotelOrderMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class HotelOrderService {

    private static final Logger log = LoggerFactory.getLogger(HotelOrderService.class);

    @Resource
    private HotelOrderMapper hotelOrderMapper;

    @Resource
    private HotelOrderItemMapper hotelOrderItemMapper;

    @Resource
    private HotelDishMapper hotelDishMapper;

    /**
     * 订单看板统计
     */
    public OrderDashboardDTO getDashboard() {
        OrderDashboardDTO dto = new OrderDashboardDTO();
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        // 各状态数量(今日)
        dto.setPendingCount(countByStatusAndDate("PLACED", today));
        dto.setPreparingCount(countByStatusAndDate("PREPARING", today));
        dto.setReadyCount(countByStatusAndDate("READY", today));
        dto.setDeliveringCount(countByStatusAndDate("DELIVERING", today));

        // 今日订单总数(排除已拒单和已退单)
        QueryWrapper<HotelOrder> totalQw = new QueryWrapper<>();
        totalQw.likeRight("create_time", today)
               .ne("status", "REJECTED")
               .ne("status", "REFUNDED");
        dto.setTodayTotal(Math.toIntExact(hotelOrderMapper.selectCount(totalQw)));

        // 今日营业额
        BigDecimal revenue = hotelOrderMapper.sumTodayRevenue(today);
        dto.setTodayRevenue(revenue != null ? revenue.toPlainString() : "0.00");

        return dto;
    }

    /**
     * 按状态和日期统计订单数
     */
    private int countByStatusAndDate(String status, String date) {
        QueryWrapper<HotelOrder> qw = new QueryWrapper<>();
        qw.likeRight("create_time", date).eq("status", status);
        return Math.toIntExact(hotelOrderMapper.selectCount(qw));
    }

    /**
     * 分页查询订单列表
     */
    public IPage<HotelOrder> findPage(Page<HotelOrder> page, HotelOrder query) {
        QueryWrapper<HotelOrder> qw = new QueryWrapper<>();
        if (query != null) {
            if (query.getRoomNo() != null && !query.getRoomNo().isEmpty()) {
                qw.eq("room_no", query.getRoomNo());
            }
            if (query.getStatus() != null && !query.getStatus().isEmpty()) {
                qw.eq("status", query.getStatus());
            }
            if (query.getContactName() != null && !query.getContactName().isEmpty()) {
                qw.like("contact_name", query.getContactName());
            }
        }
        qw.orderByDesc("create_time");
        IPage<HotelOrder> result = hotelOrderMapper.selectPage(page, qw);
        // 填充订单明细
        for (HotelOrder order : result.getRecords()) {
            fillOrderItems(order);
        }
        return result;
    }

    /**
     * 查询订单详情
     */
    public HotelOrder getDetail(String id) {
        HotelOrder order = hotelOrderMapper.selectById(id);
        if (order != null) {
            fillOrderItems(order);
        }
        return order;
    }

    /**
     * 填充订单明细
     */
    private void fillOrderItems(HotelOrder order) {
        QueryWrapper<HotelOrderItem> qw = new QueryWrapper<>();
        qw.eq("order_id", order.getId());
        order.setItems(hotelOrderItemMapper.selectList(qw));
    }

    /**
     * 创建订单(客户端下单, 使用DTO接收参数)
     */
    @Transactional(rollbackFor = Exception.class)
    public HotelOrder createOrder(OrderCreateDTO dto) {
        // 校验
        if (dto.getRoomNo() == null || dto.getRoomNo().isEmpty()) {
            throw new RuntimeException("房间号不能为空");
        }
        if (dto.getItems() == null || dto.getItems().isEmpty()) {
            throw new RuntimeException("订单明细不能为空");
        }

        // 构建订单实体
        HotelOrder order = new HotelOrder();
        order.setId(UUID.randomUUID().toString().replace("-", ""));
        order.setOrderNo(generateOrderNo());
        order.setRoomNo(dto.getRoomNo());
        order.setContactName(dto.getContactName());
        order.setContactPhone(dto.getContactPhone());
        order.setDeliveryFee(dto.getDeliveryFee() != null ? dto.getDeliveryFee() : BigDecimal.ZERO);
        order.setPayMethod(dto.getPayMethod());
        order.setDeliveryTimeType(dto.getDeliveryTimeType());
        order.setCustomDeliveryTime(dto.getCustomDeliveryTime());
        order.setNote(dto.getNote());
        order.setStatus("PLACED");
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setDelFlag(0);

        // 计算总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (HotelOrderItem item : dto.getItems()) {
            BigDecimal subtotal = item.getUnitPrice().multiply(new BigDecimal(item.getQuantity()));
            item.setSubtotal(subtotal);
            totalAmount = totalAmount.add(subtotal);
        }
        totalAmount = totalAmount.add(order.getDeliveryFee());
        order.setTotalAmount(totalAmount);

        hotelOrderMapper.insert(order);
        log.info("创建订单: {}, 房间: {}, 金额: {}", order.getOrderNo(), order.getRoomNo(), totalAmount);

        // 保存订单明细
        for (HotelOrderItem item : dto.getItems()) {
            item.setId(UUID.randomUUID().toString().replace("-", ""));
            item.setOrderId(order.getId());
            item.setCreateTime(new Date());
            item.setUpdateTime(new Date());
            item.setDelFlag(0);
            hotelOrderItemMapper.insert(item);
        }

        return order;
    }

    /**
     * 生成订单号: RM + YYYYMMDD + 4位序号
     */
    private String generateOrderNo() {
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String prefix = "RM" + dateStr;
        QueryWrapper<HotelOrder> qw = new QueryWrapper<>();
        qw.likeRight("order_no", prefix).orderByDesc("order_no").last("LIMIT 1");
        HotelOrder lastOrder = hotelOrderMapper.selectOne(qw);
        int seq = 1;
        if (lastOrder != null && lastOrder.getOrderNo() != null) {
            String lastSeq = lastOrder.getOrderNo().substring(prefix.length());
            try {
                seq = Integer.parseInt(lastSeq) + 1;
            } catch (NumberFormatException ignored) {
            }
        }
        return prefix + String.format("%04d", seq);
    }

    /**
     * 更新菜品销量
     */
    private void updateDishSales(String dishId, int quantity) {
        HotelDish dish = hotelDishMapper.selectById(dishId);
        if (dish != null) {
            dish.setSales((dish.getSales() != null ? dish.getSales() : 0) + quantity);
            hotelDishMapper.updateById(dish);
        }
    }

    /**
     * 餐厅接单
     */
    @Transactional(rollbackFor = Exception.class)
    public String acceptOrder(String orderId) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"PLACED".equals(order.getStatus())) {
            throw new RuntimeException("只有待接单的订单才能接单");
        }
        order.setStatus("ACCEPTED");
        order.setAcceptTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        log.info("订单接单: {}", order.getOrderNo());
        return "操作成功";
    }

    /**
     * 餐厅拒单(自动退款)
     */
    @Transactional(rollbackFor = Exception.class)
    public String rejectOrder(String orderId, String reason) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"PLACED".equals(order.getStatus())) {
            throw new RuntimeException("只有待接单的订单才能拒单");
        }
        order.setStatus("REJECTED");
        order.setRejectReason(reason);
        order.setRefundTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        log.info("订单拒单: {}", order.getOrderNo());
        return "操作成功";
    }

    /**
     * 开始备餐(厨房)
     */
    @Transactional(rollbackFor = Exception.class)
    public String prepareOrder(String orderId) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"ACCEPTED".equals(order.getStatus())) {
            throw new RuntimeException("只有已接单的订单才能开始备餐");
        }
        order.setStatus("PREPARING");
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        return "操作成功";
    }

    /**
     * 出餐完成(厨房)
     */
    @Transactional(rollbackFor = Exception.class)
    public String readyOrder(String orderId) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"PREPARING".equals(order.getStatus())) {
            throw new RuntimeException("只有备餐中的订单才能出餐");
        }
        order.setStatus("READY");
        order.setReadyTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        return "操作成功";
    }

    /**
     * 开始配送(餐厅前台)
     */
    @Transactional(rollbackFor = Exception.class)
    public String deliverOrder(String orderId) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"READY".equals(order.getStatus())) {
            throw new RuntimeException("只有待配送的订单才能开始配送");
        }
        order.setStatus("DELIVERING");
        order.setDeliverTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        return "操作成功";
    }

    /**
     * 完成配送
     */
    @Transactional(rollbackFor = Exception.class)
    public String completeOrder(String orderId) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"DELIVERING".equals(order.getStatus())) {
            throw new RuntimeException("只有配送中的订单才能完成");
        }
        order.setStatus("COMPLETED");
        order.setCompleteTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        // 订单完成时累加菜品销量
        incrementDishSales(orderId);
        log.info("订单完成: {}", order.getOrderNo());
        return "操作成功";
    }

    /**
     * 订单完成时累加菜品销量
     */
    private void incrementDishSales(String orderId) {
        QueryWrapper<HotelOrderItem> qw = new QueryWrapper<>();
        qw.eq("order_id", orderId).eq("del_flag", 0);
        List<HotelOrderItem> items = hotelOrderItemMapper.selectList(qw);
        for (HotelOrderItem item : items) {
            if (item.getDishId() != null) {
                HotelDish dish = hotelDishMapper.selectById(item.getDishId());
                if (dish != null) {
                    dish.setSales((dish.getSales() != null ? dish.getSales() : 0) + item.getQuantity());
                    hotelDishMapper.updateById(dish);
                }
            }
        }
    }

    /**
     * 客户自助退单(仅未接单时可退)
     */
    @Transactional(rollbackFor = Exception.class)
    public String customerRefund(String orderId, String reason) {
        HotelOrder order = checkOrderExists(orderId);
        if (!"PLACED".equals(order.getStatus())) {
            return "订单已接单，请联系前台退单";
        }
        order.setStatus("REFUNDED");
        order.setRefundReason(reason);
        order.setRefundInitiator("CUSTOMER");
        order.setRefundTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        log.info("客户退单: {}", order.getOrderNo());
        return "退单成功";
    }

    /**
     * 酒店前台退单
     */
    @Transactional(rollbackFor = Exception.class)
    public String hotelRefund(String orderId, String reason) {
        HotelOrder order = checkOrderExists(orderId);
        if ("COMPLETED".equals(order.getStatus()) || "REFUNDED".equals(order.getStatus())) {
            throw new RuntimeException("已完成或已退单的订单不能退单");
        }
        order.setStatus("REFUNDED");
        order.setRefundReason(reason);
        order.setRefundInitiator("HOTEL_DESK");
        order.setRefundTime(new Date());
        order.setUpdateTime(new Date());
        hotelOrderMapper.updateById(order);
        log.info("前台退单: {}", order.getOrderNo());
        return "操作成功";
    }

    /**
     * 按房间号查询订单列表
     */
    public List<HotelOrder> findByRoomNo(String roomNo) {
        QueryWrapper<HotelOrder> qw = new QueryWrapper<>();
        qw.eq("room_no", roomNo).orderByDesc("create_time");
        List<HotelOrder> list = hotelOrderMapper.selectList(qw);
        for (HotelOrder order : list) {
            fillOrderItems(order);
        }
        return list;
    }

    /**
     * 统计今日订单数
     */
    public int countTodayOrders() {
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<HotelOrder> qw = new QueryWrapper<>();
        qw.likeRight("create_time", today)
          .ne("status", "REJECTED")
          .ne("status", "REFUNDED");
        return Math.toIntExact(hotelOrderMapper.selectCount(qw));
    }

    /**
     * 校验订单是否存在
     */
    private HotelOrder checkOrderExists(String orderId) {
        HotelOrder order = hotelOrderMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        return order;
    }
}
