package shop.alien.store.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import shop.alien.entity.store.MerchantPaymentOrder;
import shop.alien.entity.store.StoreBookingCategory;
import shop.alien.entity.store.StoreBookingTable;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.UserReservation;
import shop.alien.entity.store.UserReservationOrder;
import shop.alien.entity.store.UserReservationTable;
import shop.alien.mapper.UserReservationTableMapper;
import shop.alien.store.service.*;
import shop.alien.store.vo.ReservationOrderPageVo;

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

/**
 * 预订订单页面展示服务实现
 *
 * @author system
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ReservationOrderPageServiceImpl implements ReservationOrderPageService {

    private static final int PAYMENT_DEADLINE_MINUTES = 15;
    private static final int ORDER_STATUS_UNPAID = 0;
    private static final int ORDER_STATUS_TO_USE = 1;
    private static final int CANCELLATION_FREE = 0;
    private static final int CANCELLATION_NOT_FREE = 1;
    private static final int CANCELLATION_CONDITIONAL = 2;

    private static final int ORDER_STATUS_COMPLETED = 2;
    private static final int ORDER_STATUS_EXPIRED = 3;
    private static final int ORDER_STATUS_CANCELLED = 4;
    private static final int ORDER_STATUS_CLOSED = 5;
    private static final int ORDER_STATUS_REFUNDING = 6;
    private static final int ORDER_STATUS_REFUNDED = 7;

    private final UserReservationOrderService userReservationOrderService;
    private final StoreInfoService storeInfoService;
    private final UserReservationService userReservationService;
    private final UserReservationTableMapper userReservationTableMapper;
    private final StoreBookingTableService storeBookingTableService;
    private final StoreBookingCategoryService storeBookingCategoryService;
    private final MerchantPaymentOrderService merchantPaymentOrderService;

    @Override
    public ReservationOrderPageVo getPageByOrderId(Integer orderId) {
        if (orderId == null) {
            return null;
        }
        UserReservationOrder order = userReservationOrderService.getById(orderId);
        if (order == null) {
            return null;
        }
        return buildPageVo(order.getStoreId(), order);
    }

    private ReservationOrderPageVo buildPageVo(Integer storeId, UserReservationOrder order) {
        ReservationOrderPageVo vo = new ReservationOrderPageVo();
        vo.setOrderId(order.getId());
        vo.setOrderSn(order.getOrderSn());
        vo.setOrderStatus(order.getOrderStatus());
        vo.setPaymentStatus(order.getPaymentStatus() != null ? order.getPaymentStatus() : derivePaymentStatus(order.getOrderStatus()));
        vo.setPayAmount(order.getDepositAmount() != null ? order.getDepositAmount() : BigDecimal.ZERO);
        vo.setPaymentDeadlineMinutes(PAYMENT_DEADLINE_MINUTES);

        // 支付倒计时
        vo.setPaymentDeadline(order.getPaymentDeadline());
        int secondsLeft = computePaymentSecondsLeft(order);
        vo.setPaymentSecondsLeft(secondsLeft);
        vo.setCanContinuePay(Boolean.valueOf(ORDER_STATUS_UNPAID == order.getOrderStatus() && secondsLeft > 0));

        // 页面标题与后缀（全状态）；已取消时在加载 reservation 后根据 reason 区分为用户取消/商家取消
        Integer orderStatus = order.getOrderStatus();
        vo.setPageTitle(buildPageTitle(orderStatus, null));
        vo.setPageTitleSuffix(buildPageTitleSuffixByStatus(orderStatus, order.getCancellationPolicyType(), order.getOrderCostType()));
        vo.setStatusSubtitle(buildStatusSubtitle(order));

        // 操作按钮
        vo.setCanCancelReservation(Boolean.valueOf(ORDER_STATUS_UNPAID == orderStatus || ORDER_STATUS_TO_USE == orderStatus));
        vo.setCanModifyReservation(Boolean.valueOf(ORDER_STATUS_TO_USE == orderStatus));
        boolean endState = orderStatus != null && (orderStatus == ORDER_STATUS_COMPLETED || orderStatus == ORDER_STATUS_EXPIRED
                || orderStatus == ORDER_STATUS_CANCELLED || orderStatus == ORDER_STATUS_CLOSED
                || orderStatus == ORDER_STATUS_REFUNDING || orderStatus == ORDER_STATUS_REFUNDED);
        vo.setCanDelete(endState);
        vo.setCanBookAgain(endState);

        // 待支付时返回当前支付单的 outTradeNo（用于轮询 queryStatus）
        if (orderStatus != null && ORDER_STATUS_UNPAID == orderStatus) {
            MerchantPaymentOrder unpaid = merchantPaymentOrderService.getUnpaidByOrderId(order.getId());
            if (unpaid != null) {
                vo.setOutTradeNo(unpaid.getOutTradeNo());
            }
        }

        // 门店
        if (storeId != null) {
            StoreInfo store = storeInfoService.getById(storeId);
            if (store != null) {
            vo.setStoreId(storeId);
            vo.setStoreName(store.getStoreName());
            vo.setStoreAddress(store.getStoreAddress());
            vo.setStoreTel(store.getStoreTel());
            vo.setStorePosition(store.getStorePosition());
            }
        }

        // 预约信息
        if (order.getReservationId() != null) {
            UserReservation reservation = userReservationService.getById(order.getReservationId());
            if (reservation != null) {
                vo.setReservationDate(reservation.getReservationDate());
                vo.setReservationDateText(formatDateWithToday(reservation.getReservationDate()));
                vo.setGuestCount(reservation.getGuestCount());
                vo.setDiningTimeSlotText(buildDiningTimeSlot(reservation.getStartTime(), reservation.getEndTime()));
                vo.setDiningTimeText(buildDiningTimeSlot(reservation.getStartTime(), reservation.getEndTime()));

                List<Integer> tableIds = listTableIdsByReservationId(reservation.getId());
                List<StoreBookingTable> tables = new ArrayList<>();
                String categoryName = null;
                for (Integer tableId : tableIds) {
                    StoreBookingTable t = storeBookingTableService.getById(tableId);
                    if (t != null) {
                        tables.add(t);
                        if (categoryName == null && t.getCategoryId() != null) {
                            StoreBookingCategory cat = storeBookingCategoryService.getById(t.getCategoryId());
                            if (cat != null) {
                                categoryName = cat.getCategoryName();
                            }
                        }
                    }
                }
                String tableNumbersText = tables.stream().map(StoreBookingTable::getTableNumber).filter(Objects::nonNull).collect(Collectors.joining(","));
                vo.setTableNumbersText(tableNumbersText.isEmpty() ? null : tableNumbersText);
                vo.setGuestAndCategoryText(buildGuestAndCategoryText(categoryName, reservation.getGuestCount(), tables));
                vo.setLocationTableText(buildLocationTableText(categoryName, tableNumbersText));
                if (orderStatus != null && orderStatus == 4) {
                    vo.setPageTitle(buildPageTitle(4, reservation));
                }
            }
        }

        // 使用凭证
        vo.setVerificationCode(order.getVerificationCode());
        vo.setVerificationUrl(order.getVerificationUrl());

        // 预订说明（待支付与待使用页面共用）
        Integer graceMinutes = order.getLateArrivalGraceMinutes() != null ? order.getLateArrivalGraceMinutes() : 0;
        vo.setLateArrivalGraceMinutes(graceMinutes);
        if (graceMinutes != null && graceMinutes > 0) {
            vo.setSeatRetentionText("未按时到店座位保留" + graceMinutes + "分钟");
        } else {
            vo.setSeatRetentionText("未按时到店座位将不会保留");
        }
        vo.setDepositAmount(order.getDepositAmount());
        vo.setDepositText(order.getDepositAmount() != null && order.getDepositAmount().compareTo(BigDecimal.ZERO) > 0
                ? "需支付¥" + order.getDepositAmount().stripTrailingZeros().toPlainString() + "订金"
                : null);
        vo.setDepositRefundRule(order.getDepositRefundRule());
        vo.setCancellationPolicyType(order.getCancellationPolicyType());
        vo.setFreeCancellationDeadline(order.getFreeCancellationDeadline());
        vo.setFreeCancellationDeadlineText(formatFreeCancellationDeadline(order.getFreeCancellationDeadline()));
        vo.setCancellationPolicyText(buildCancellationPolicyText(order));

        // 订单信息
        vo.setOrderCreatedTime(order.getCreatedTime());
        vo.setOrderCreatedTimeText(order.getCreatedTime() != null ? formatDateWithToday(order.getCreatedTime()) : null);
        vo.setContactName(null);
        vo.setContactPhone(null);
        vo.setContactText(null);

        return vo;
    }

    private List<Integer> listTableIdsByReservationId(Integer reservationId) {
        return userReservationTableMapper.selectList(
                new LambdaQueryWrapper<UserReservationTable>()
                        .eq(UserReservationTable::getReservationId, reservationId)
                        .orderByAsc(UserReservationTable::getSort)
                        .orderByAsc(UserReservationTable::getId)
        ).stream().map(UserReservationTable::getTableId).collect(Collectors.toList());
    }

    private int computePaymentSecondsLeft(UserReservationOrder order) {
        if (order.getOrderStatus() == null || order.getOrderStatus() != ORDER_STATUS_UNPAID || order.getPaymentDeadline() == null) {
            return 0;
        }
        long now = System.currentTimeMillis();
        long deadline = order.getPaymentDeadline().getTime();
        long diff = (deadline - now) / 1000;
        return diff > 0 ? (int) diff : 0;
    }

    /**
     * 页面主标题。orderStatus=4 时若传入 reservation，根据 user_reservation.reason 区分：reason 不为空为「商家取消」，否则「用户取消」
     */
    private String buildPageTitle(Integer orderStatus, UserReservation reservation) {
        if (orderStatus == null) return null;
        if (orderStatus == 4 && reservation != null) {
            return org.apache.commons.lang3.StringUtils.isNotBlank(reservation.getReason()) ? "商家取消" : "用户取消";
        }
        switch (orderStatus) {
            case 0: return "待支付";
            case 1: return "预订成功";
            case 2: return "已完成";
            case 3: return "已过期";
            case 4: return "已取消";
            case 5: return "已关闭";
            case 6: return "退款中";
            case 7: return "已退款";
            default: return null;
        }
    }

    private String buildPageTitleSuffixByStatus(Integer orderStatus, Integer cancellationPolicyType, Integer orderCostType) {
        if (orderStatus == null) return "不可免责取消";
        if (orderStatus == 0) return buildPendingPaymentTitleSuffix(cancellationPolicyType);
        if (orderStatus == 1) return buildSuccessPageTitleSuffix(cancellationPolicyType);
        if (orderStatus == 2 || orderStatus == 3 || orderStatus == 4 || orderStatus == 5 || orderStatus == 6 || orderStatus == 7) {
            if (orderCostType != null && orderCostType == 0) return "免费预订";
            if (cancellationPolicyType == null) return "不可免责取消";
            if (cancellationPolicyType == CANCELLATION_FREE) return "免费预订";
            if (cancellationPolicyType == CANCELLATION_CONDITIONAL) return "分情况是否免责";
            return "不可免责取消";
        }
        return buildPendingPaymentTitleSuffix(cancellationPolicyType);
    }

    private String buildStatusSubtitle(UserReservationOrder order) {
        if (order == null) return null;
        Integer status = order.getOrderStatus();
        if (ORDER_STATUS_COMPLETED == status && order.getPaymentStatus() != null && order.getPaymentStatus() == 2) {
            return "退款成功,已按原支付路径返回";
        }
        if (ORDER_STATUS_REFUNDING == status) {
            return "正在为您发起退款,请耐心等待";
        }
        if (ORDER_STATUS_CANCELLED == status) {
            Integer refundType = order.getRefundType();
            if (refundType != null && refundType == 0) {
                if (order.getOrderCostType() != null && order.getOrderCostType() == 0) return "用户取消-免费预订";
                if (order.getCancellationPolicyType() != null && order.getCancellationPolicyType() == CANCELLATION_NOT_FREE) return "用户取消-不可免费";
                if (order.getCancellationPolicyType() != null && order.getCancellationPolicyType() == CANCELLATION_CONDITIONAL) return "用户取消-分情况是否免责";
            }
            if (order.getPaymentStatus() != null && order.getPaymentStatus() == 2) return "取消成功，已将订单费用原路退还";
        }
        return null;
    }

    private String buildPendingPaymentTitleSuffix(Integer cancellationPolicyType) {
        if (cancellationPolicyType == null) return "不可免责取消";
        if (cancellationPolicyType == CANCELLATION_FREE) return "免费预订";
        if (cancellationPolicyType == CANCELLATION_CONDITIONAL) return "分情况是否免责";
        return "不可免责取消";
    }

    private String buildSuccessPageTitleSuffix(Integer cancellationPolicyType) {
        if (cancellationPolicyType == null) return "不可免责";
        if (cancellationPolicyType == CANCELLATION_FREE) return "免费预订";
        if (cancellationPolicyType == CANCELLATION_CONDITIONAL) return "分情况是否免责";
        return "不可免责";
    }

    private String buildDiningTimeSlot(String startTime, String endTime) {
        if (startTime == null && endTime == null) return null;
        if (startTime != null && endTime != null) return startTime + "-" + endTime;
        return startTime != null ? startTime : endTime;
    }

    private String buildGuestAndCategoryText(String categoryName, Integer guestCount, List<StoreBookingTable> tables) {
        int capacity = tables.stream().mapToInt(t -> t.getSeatingCapacity() != null ? t.getSeatingCapacity() : 0).max().orElse(guestCount != null ? guestCount : 0);
        if (capacity <= 0 && guestCount != null) capacity = guestCount;
        String part = categoryName != null ? categoryName : "预订";
        return part + (capacity > 0 ? capacity + "人" : "");
    }

    private String buildLocationTableText(String categoryName, String tableNumbersText) {
        if (categoryName != null && tableNumbersText != null && !tableNumbersText.isEmpty()) {
            return categoryName + "|" + tableNumbersText;
        }
        if (tableNumbersText != null && !tableNumbersText.isEmpty()) return tableNumbersText;
        return categoryName;
    }

    private String formatDateWithToday(Date date) {
        if (date == null) return null;
        SimpleDateFormat f = new SimpleDateFormat("MM月dd日", Locale.CHINA);
        String s = f.format(date);
        Calendar cal = Calendar.getInstance();
        Calendar d = Calendar.getInstance();
        d.setTime(date);
        if (cal.get(Calendar.YEAR) == d.get(Calendar.YEAR) && cal.get(Calendar.DAY_OF_YEAR) == d.get(Calendar.DAY_OF_YEAR)) {
            s += " 今天";
        }
        return s;
    }

    private String formatFreeCancellationDeadline(Date deadline) {
        if (deadline == null) return null;
        SimpleDateFormat f = new SimpleDateFormat("MM月dd日 HH:mm", Locale.CHINA);
        return f.format(deadline) + "前可免责取消";
    }

    private String buildCancellationPolicyText(UserReservationOrder order) {
        Integer type = order.getCancellationPolicyType();
        if (type == null) return "取消将收取订金";
        if (type == CANCELLATION_FREE) return "免费取消";
        if (type == CANCELLATION_NOT_FREE) return "不可免责取消，取消将收取订金";
        if (type == CANCELLATION_CONDITIONAL) {
            String line = formatFreeCancellationDeadline(order.getFreeCancellationDeadline());
            return line != null ? line + "；在上述时间前取消订金可原路返回，之后取消将收取订金" : "分情况是否免责，取消将收取订金";
        }
        return "取消将收取订金";
    }

    /** 根据订单状态推导支付状态 0:未支付 1:已支付 2:已退款 */
    private int derivePaymentStatus(Integer orderStatus) {
        if (orderStatus == null) return 0;
        if (orderStatus == 0) return 0;
        if (orderStatus == 6 || orderStatus == 7) return 2;
        return 1;
    }
}
