package com.happy.service.impl;

import com.baidubce.model.User;
import com.happy.Model.*;
import com.happy.Model.weixin.Users;
import com.happy.Until.DateUtil;
import com.happy.Until.Enum.OrderEnum;
import com.happy.Until.Enum.PayEnum;
import com.happy.Until.Func;
import com.happy.Until.TimeExchange;
import com.happy.Until.UUIDUtil;
import com.happy.common.wx.WxUtil;
import com.happy.constant.ResultStatusCode;
import com.happy.dao.BookDao;
import com.happy.dto.IPage;
import com.happy.service.*;
import com.happy.vo.DailyPriceVo;
import com.happy.vo.HousePriceDataVo;
import com.happy.vo.HousePriceOneDataVo;
import com.happy.vo.HousePriceResultVo;
import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;


@Service("AppBookService")
public class AppBookImplService implements AppBookService {

    @Resource
    public BookService bookService;
    @Resource
    public BookinglogService bookinglogService;
    @Resource
    public HotelService hotelService;
    @Resource
    public HouseService houseService;
    @Resource
    public UserService userService;
    @Resource
    public HotelDictService hotelDictService;
    @Resource
    public AdminManagerService adminManagerService;
    @Resource
    public HousePriceService housePriceService;

    @Resource
    public HotelCoupomService hotelCoupomService;
    @Resource
    public HotelCoupomStatusService hotelCoupomStatusService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(String bookingId, String houseId, String startTime, String endTime, String houseOrderNumber, String userName, String userPhone, String userId, String complaintId, String useId) throws ParseException {
        if (Func.checkNull(houseId) || Func.checkNull(startTime) || Func.checkNull(endTime)
                || Func.checkNull(houseOrderNumber) || Func.checkNull(userName) || Func.checkNull(userPhone) || Func.checkNull(userId))
            return null;

        House house = houseService.getById(houseId);
        StringBuilder s1 = new StringBuilder("");
        s1.append(" and manager_id = '").append(house.getManagerId()).append("' ");
        Hotel hotel = hotelService.getOen(s1.toString());
        Users user = userService.queryByUserId(userId);
        AdminManager adminManager = adminManagerService.getById(Func.parseInt(house.getManagerId()));
        if (house == null || hotel == null || user == null || adminManager == null)
            return "无法获取数据";

        Booking booking = new Booking();

        int day = DateUtil.getDayDiff(startTime, endTime); // 中间多少天
        String orderLiveTime = Func.parseInt(houseOrderNumber) + OrderEnum.间.toString() + day + OrderEnum.晚.toString();
        String hotelType = hotelDictService.getDictNameById(Integer.parseInt(hotel.getHtype()));// 民宿类型hotel.getHtype()


        // 设置民宿信息
        booking.setHotelId(Func.parseStr(hotel.getId()));
        booking.setHotelName(adminManager.getHotelName()); // 创建表单的时候，取酒店名称(数据来源于admin_manager中的hotelname)
        booking.setHotelHposition(hotel.getHposition());
        booking.setHotelHpositionWens(hotel.getHpositionWens());
        booking.setHotelManagerId(hotel.getManagerId());
        booking.setHotelTownship(adminManager.getHotelTownship());
        booking.setHotelConfig(hotel.getHconfig());
        booking.setHotelType(hotelType);  // 民宿类型（舒适形、舒适型、包吃住型、普通型）
        booking.setHotelIsCanorder(Func.parseStr(hotel.getIsCanorder())); // 是否自动取消订单
        booking.setHotelIsOrder(Func.parseStr(hotel.getIsOrder())); // 是否自动接单
        booking.setHotelIsCheckout(Func.parseStr(hotel.getIsCheckout())); // 是否自动离店
        booking.setHotelPhone(adminManager.getCorpnPhone());
        booking.setHotelPerson(adminManager.getCorpnName());
        booking.setLockTime(hotel.getLockTime());

        // 设置房型信息
        booking.setHouseId(Func.parseStr(house.getId()));
        booking.setHouseName(house.gethName());
        booking.setHouseConfig(house.gethConfig());
        booking.setHouseUnitPrice(house.getPrice());
        booking.setHouseOrderNumber(Func.parseInt(houseOrderNumber));
        booking.setHouseAreas(house.gethAreas());
        booking.setHouseRemake(house.getRemark());

        /**
         * 2023-09-15 A-jax 订单总价等于房间数量 * 这些天的价格总和
         */
        List<HousePriceDataVo> priceDatas = housePriceService.queryPriceByHouseId(house.getId(), startTime, TimeExchange.TimeDesD(endTime, -1));

        List<HousePriceOneDataVo> oneDatas = new ArrayList<>();
        //将数据处理成单天的
        for (HousePriceDataVo hp : priceDatas) {
            if (hp.getStartTime().equals(hp.getEndTime())) {
                HousePriceOneDataVo oneData = new HousePriceOneDataVo();
                oneData.setSetDate(hp.getStartTime());
                oneData.setCreateDate(hp.getCreateDate());
                oneData.setPrice(hp.getPrice());
                oneData.setHouseId(hp.getHouseId());
                oneDatas.add(oneData);
            } else {
                int beDateNum = TimeExchange.daysBetween(hp.getStartTime(), hp.getEndTime());
                for (int i = 0; i <= beDateNum; i++) {
                    HousePriceOneDataVo oneData = new HousePriceOneDataVo();
                    oneData.setSetDate(TimeExchange.TimeDesD(hp.getStartTime(), i));
                    oneData.setCreateDate(hp.getCreateDate());
                    oneData.setPrice(hp.getPrice());
                    oneData.setHouseId(hp.getHouseId());
                    oneDatas.add(oneData);
                }
            }
        }

        List<String> dateStrs = new ArrayList<>();
        int dateNum = TimeExchange.daysBetween(startTime, endTime);
        for (int i = 0; i <= dateNum; i++) {
            String date = TimeExchange.TimeDesD(startTime, i);
            dateStrs.add(date);
        }

        /**
         * 获取该房型默认价格
         */
        Double housePrice = houseService.queryPriceByHouseId(house.getId());
        Double dayPrices = 0.0;
        for (String dateStr : dateStrs) {
            HousePriceResultVo data = new HousePriceResultVo();
            data.setDate(dateStr);
            List<HousePriceOneDataVo> datas = oneDatas.stream().filter(e -> e.getSetDate().equals(dateStr)).sorted(Comparator.comparing(HousePriceOneDataVo::getCreateDate, Comparator.reverseOrder())).collect(Collectors.toList());

            if (!dateStr.equals(endTime)) {
                if (datas.size() > 0) {
                    dayPrices = dayPrices + datas.get(0).getPrice();
                } else {
                    dayPrices = dayPrices + housePrice;
                }
            }
        }

        double totalPrice = Func.parseDbl(houseOrderNumber) * dayPrices;

        if (!Func.checkNull(complaintId) && !Func.checkNull(useId)) {
            HotelCouponStatus hotelCouponStatus = hotelCoupomStatusService.getById(useId);
            if (hotelCouponStatus != null) {
                hotelCouponStatus.setStatus(2);
                hotelCouponStatus.setBookingId(bookingId);
                BigDecimal totalPriceBigDecimal = new BigDecimal(totalPrice);

                //        优惠券
                HotelCoupon hotelCoupon = hotelCoupomService.getById(complaintId);
                Integer type = hotelCoupon.getType();
                if (1 == type) {
//            满减金额
                    Double meetPrice = hotelCoupon.getMeetPrice();
                    BigDecimal meetPriceBigDecimal = new BigDecimal(meetPrice);
//             实际金额大于等于满减金额则可以使用
                    if (meetPrice <= totalPrice) {
                        //            减免金额
                        Double deductionPrice = hotelCoupon.getDeductionPrice();
                        BigDecimal deductionPriceBigDecimal = new BigDecimal(deductionPrice);
                        //            实付金额
                        BigDecimal subtract = totalPriceBigDecimal.subtract(deductionPriceBigDecimal);
                        totalPrice = subtract.doubleValue();
                        hotelCouponStatus.setDiscountAmount(deductionPrice);
                        hotelCoupomStatusService.update(hotelCouponStatus);
                    }

                } else if (2 == type) {
//            享受的折扣
                    Double rebatePrice = hotelCoupon.getRebatePrice();
                    BigDecimal rebatePriceBigDecimal = new BigDecimal(rebatePrice / 10);

//            最大减免金额
                    Double maxDeduction = hotelCoupon.getMaxDeduction();
                    BigDecimal maxDeductionBigDecimal = new BigDecimal(maxDeduction);

//            折扣后的价格
                    BigDecimal bigDecimal = totalPriceBigDecimal.multiply(rebatePriceBigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
                    double v = bigDecimal.doubleValue();

//            减去最大折扣后的价格
                    BigDecimal subtract = totalPriceBigDecimal.subtract(maxDeductionBigDecimal);
                    double v1 = subtract.doubleValue();

                    if (v > v1) {
                        totalPrice = v;
                        BigDecimal subtract1 = totalPriceBigDecimal.subtract(bigDecimal);
                        hotelCouponStatus.setDiscountAmount(subtract1.doubleValue());
                    } else if (v < v1) {
                        totalPrice = v1;
                        hotelCouponStatus.setDiscountAmount(maxDeduction);
                    } else if (v == v1) {
                        totalPrice = v1;
                        hotelCouponStatus.setDiscountAmount(maxDeduction);
                    }

                    hotelCoupomStatusService.update(hotelCouponStatus);

                }
            }
        }

        booking.setHouseTotalPrice(totalPrice);
        booking.setOrderAccount(totalPrice);

        // 设置住客信息
        booking.setUserName(userName);
        booking.setUserPhone(userPhone);
        booking.setOrderStartTime(startTime);
        booking.setOrderEndTime(endTime);
        booking.setOrderLiveTime(orderLiveTime);

        // 订单信息
        booking.setOrderNum(Func.parseStr(WxUtil.mchOrderNo()));// 订单号
        booking.setOrderStatus(Func.parseStr(PayEnum.待支付.getNum())); // 1待支付状态
        booking.setCreateTime(DateUtil.getFormatPaternDate(DateUtil.getCurrentDate()));
        booking.setCreateUserid(userId);
        booking.setId(Func.parseInt(bookingId));
        int i = bookService.insertBooking(booking);

        // 生成订单时，写入数据操作
        bookinglogService.addBooklog(OrderEnum.生成订单.toString(), booking);

        if (i == 0) {
//            返还优惠券
            HotelCouponStatus hotelCouponStatus = hotelCoupomStatusService.getById(useId);
            hotelCouponStatus.setStatus(1);
            hotelCouponStatus.setBookingId(null);
            hotelCouponStatus.setDiscountAmount(null);
            hotelCoupomStatusService.update(hotelCouponStatus);

            return ResultStatusCode.CANNTBOOKING.CANNTBOOKING.getMsg();
        }
        return null;
    }

    @Override
    public String varificationHouse(String houseId, String startTime, String endTime, String houseOrderNumber) {
        House house = houseService.getById(houseId);
        if (house == null)
            return "无此房间，请重新查询";
        if (Func.checkNull(houseOrderNumber))
            houseOrderNumber = "0";

        if (house.getNumber() < Func.parseInt(houseOrderNumber))
            return OrderEnum.超出限定房间数量.toString();

        // 判断是否有房间，对每个房型进行标识
        StringBuffer strSqlBook = new StringBuffer();
        strSqlBook.append(" and house_id = '").append(house.getId()).append("' ");
        strSqlBook.append(" and hotel_manager_id = '").append(house.getManagerId()).append("' ");
//        if (!Func.checkNull(startTime))
//            strSqlBook.append(" and order_start_time >= '").append(startTime).append(" 00:00:00  ' ");
//        if (!Func.checkNull(endTime))
//            strSqlBook.append(" and order_end_time < '").append(endTime).append(" 23:59:59 ' ");

        //1待支付,2已支付,3待入住,4已入住,5已消费,6支付超时,7已取消,8已退单,9已退款
        strSqlBook.append(" and  ( order_status = '").append(PayEnum.待支付.getNum()).append("' ");
        strSqlBook.append(" or order_status = '").append(PayEnum.已支付.getNum()).append("' ");
        strSqlBook.append(" or order_status = '").append(PayEnum.待入住.getNum()).append("' ");
        strSqlBook.append(" or order_status = '").append(PayEnum.已入住.getNum()).append("' ) ");

        List<Booking> bookList = bookService.queryList(strSqlBook.toString());
        if (bookList == null)
            return null;

        Map<String, Integer> timeMap = new HashMap(); // map<时间，天数>进行累加
//        int totalNum = 0;
        for (Booking booking : bookList) {
            if (Func.checkNull(booking.getHouseId()))
                continue;

            int day = DateUtil.getDayDiff(booking.getOrderStartTime(), booking.getOrderEndTime());
            for (int i = 0; i < day; i++) {
                String time = DateUtil.parseDateToStr(DateUtil.addDate(DateUtil.parseDateOnly(booking.getOrderStartTime()), Calendar.DATE, i), DateUtil.Time_Formatter_Day);
                if (!timeMap.containsKey(time)) {
                    timeMap.put(time, booking.getHouseOrderNumber());
                    continue;
                }

                timeMap.put(time, booking.getHouseOrderNumber() + Func.parseInt(timeMap.get(time)));
            }
        }

        List<String> dayQueryList = new ArrayList();
        // 遍历查询的每一天当做一个列表数据
        int dayQuerys = DateUtil.getDayDiff(startTime, endTime);
        for (int i = 0; i < dayQuerys; i++) {
            String time = DateUtil.parseDateToStr(DateUtil.addDate(DateUtil.parseDateOnly(startTime), Calendar.DATE, i), DateUtil.Time_Formatter_Day);
            dayQueryList.add(time);
        }


        for (String dayQuery : dayQueryList) {
            if (Func.checkNull(dayQuery))
                continue;

            if (timeMap.containsKey(dayQuery)) {
                int totalNum = timeMap.get(dayQuery); // 当天房间的数量
                // 订单中房数量》= 总房间数量 表示已满
                if (totalNum >= house.getNumber())
                    return dayQuery + OrderEnum.房间已满.toString();

                // 现存房数量 《 要订的订房数量   表示已满
                if ((house.getNumber() - totalNum) < Func.parseInt(houseOrderNumber))
                    return dayQuery + OrderEnum.房间已满.toString();
            }

        }


        return null;
    }

}
