package com.happy.service.impl;

import com.happy.Model.Booking;
import com.happy.Model.FileInfo;
import com.happy.Model.Hotel;
import com.happy.Model.House;
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.dao.BookDao;
import com.happy.dao.HouseDao;
import com.happy.dto.IPage;
import com.happy.service.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("AppHomePageService")
public class AppHomePageImplService implements AppHomePageService {

    @Resource
    public BookDao bookDao;
    @Resource
    public HouseDao houseDao;
    @Resource
    public HouseService houseService;
    @Resource
    public HotelService hotelService;
    @Resource
    public BookService bookService;
    @Resource
    public AdminManagerService adminManagerService;
    @Resource
    public FileService fileService;
    @Resource
    public UserService userService;


    @Override
    public IPage<Hotel> getHotelList(String queryValue,String hotel_township, int page, int rows) {
        StringBuilder strSql = new StringBuilder(" and hstatus=1 "); // 酒店正在营业中才显示
        if (!Func.checkNull(queryValue)){
            strSql.append(" and hname like '%").append(queryValue).append("%' ");
        }
        if (!Func.checkNull(hotel_township)){
            strSql.append(" and c.hotel_township = '").append(hotel_township).append("' ");
        }
        return hotelService.queryPagePrice(strSql.toString(),page,rows);
    }

    @Override
    public IPage<Hotel> getHotelList(String queryValue,String hotel_township,int type, int page, int rows) {
        StringBuilder strSql = new StringBuilder(" and hstatus=1 "); // 酒店正在营业中才显示
        if (!Func.checkNull(queryValue)){
            strSql.append(" and hname like '%").append(queryValue).append("%' ");
        }
        if (!Func.checkNull(hotel_township)){
            strSql.append(" and c.hotel_township = '").append(hotel_township).append("' ");
        }
        if (!Func.checkNull(String.valueOf(type))){
            strSql.append(" and c.type = '").append(type).append("' ");
        }
        return hotelService.queryPagePrice(strSql.toString(),page,rows);
    }

    /**
     * 优选
     * @param queryValue
     * @param hotel_township
     * @param type
     * @param page
     * @param rows
     * @return
     */
    @Override
    public IPage<Hotel> getPreferredHotelList(String queryValue, String hotel_township, int type, int page, int rows) {
        StringBuilder strSql = new StringBuilder(" and hstatus=1 "); // 酒店正在营业中才显示
        if (!Func.checkNull(queryValue)){
            strSql.append(" and hname like '%").append(queryValue).append("%' ");
        }
        if (!Func.checkNull(hotel_township)){
            strSql.append(" and c.hotel_township = '").append(hotel_township).append("' ");
        }
        if (!Func.checkNull(String.valueOf(type))){
            strSql.append(" and c.type = '").append(type).append("' ");
        }
        return hotelService.queryPreferredPagePrice(strSql.toString(),page,rows);
    }

    /**
     * 精选
     * @param queryValue
     * @param hotel_township
     * @param type
     * @param page
     * @param rows
     * @return
     */
    @Override
    public IPage<Hotel> getSelectedHotelList(String queryValue, String hotel_township, int type, int page, int rows) {
        StringBuilder strSql = new StringBuilder(" and hstatus=1 "); // 酒店正在营业中才显示
        if (!Func.checkNull(queryValue)){
            strSql.append(" and hname like '%").append(queryValue).append("%' ");
        }
        if (!Func.checkNull(hotel_township)){
            strSql.append(" and c.hotel_township = '").append(hotel_township).append("' ");
        }
        if (!Func.checkNull(String.valueOf(type))){
            strSql.append(" and c.type = '").append(type).append("' ");
        }
        return hotelService.querySelectedPagePrice(strSql.toString(),page,rows);
    }

    @Override
    public IPage<Hotel> getHotelList(List<String> ids, int page, int rows) {
        if (ids == null || ids.size() <= 0 )
            return null;

        StringBuilder strSql = new StringBuilder(" and hstatus=1 "); // 酒店正在营业中才显示" and hstatus=1 "
        strSql.append(" and a.id in( ");
        for (String id: ids) {
            if (Func.checkNull(id)) {
                continue;
            }
//            去掉前面的null
            id=id.replaceAll("null","");
            strSql.append(" "+ id + ",");
        }
        strSql.delete(strSql.length() - 1, strSql.length());
        strSql.append(" )");

        return hotelService.queryPagePrice(strSql.toString(),page,rows);
    }

    @Override
    public int getHotelTotal(String queryValue) {



        return 0;
    }

    @Override
    public Hotel assignCollect(String userId, Hotel hotel)
    {
        Users users = userService.queryByUserId(userId);
        if (users == null || hotel == null)
            throw new RuntimeException("无法查询到当前用户");

        hotel.setCollect_hotel(users.getCollect_hotel());

        boolean flag = false; // 标识是否收获过当前酒店，Collect_hotel为空时未收藏， Collect_hotel未包含hotelid未收藏
        if (!Func.checkNull(users.getCollect_hotel()))
        {
            String collect_hotel = users.getCollect_hotel();
            flag = collect_hotel.contains(hotel.getId()+"");
        }
        hotel.setIs_collect_hotel(flag);
        return hotel;
    }

    @Override
    public Hotel getHotelAndHouseByHotelId(String hotelId, String queryStartTime, String queryEndTime) {
        if (Func.checkNull(hotelId))
            return new Hotel();
        Hotel hotel = hotelService.getById(Func.parseInt(hotelId));
        if (hotel == null || Func.checkNull(String.valueOf(hotel.getManagerId())))
            return hotel;

        // 数据字典写入hotel
        Map dicMap = hotelService.queryHotelDicMap();
        if (!Func.checkNull(hotel.getHconfig()))
        {
            List<String> list = Arrays.asList(hotel.getHconfig().split(","));
            List hotelDicList = new ArrayList();
            for (String hotelDicId:list) {
                if (!dicMap.containsKey(Func.parseInt(hotelDicId)))
                    continue;

                hotelDicList.add(dicMap.get(Func.parseInt(hotelDicId)));
            }
            hotel.setHconfigList(hotelDicList);
        }

        System.out.println(hotel.getManagerId());// 需求确定使用商户id关联房型
        StringBuffer strSql = new StringBuffer();
        strSql.append(" and manager_id = '").append(hotel.getManagerId()).append("' ");
        List<House> houseList = houseService.queryList(strSql.toString());
        if (houseList == null )
            return hotel;

        // 数据字典写入hotel
        List<String> hlist = new ArrayList<>();
        List houseDicList = new ArrayList();
        Map<String,House> houseMap = new HashMap<>();
        for (House house:houseList) {
            if (house == null || Func.checkNull(Func.parseStr(house.getNumber())))
                continue;

            houseMap.put(Func.parseStr(house.getId()),house);
            // “，”号分逗开来
            hlist = Arrays.asList(house.gethConfig().split(","));
            houseDicList = new ArrayList();
            for (String houseDicId:hlist) {
                if (!dicMap.containsKey(Func.parseInt(houseDicId)))
                    continue;

                houseDicList.add(dicMap.get(Func.parseInt(houseDicId)));
            }
            house.sethConfigList(houseDicList);
        }

        // 判断是否有房间，对每个房型进行标识
        StringBuffer strSqlBook = new StringBuffer();
        strSqlBook.append(" and hotel_manager_id = '").append(hotel.getManagerId()).append("  ' ");

        //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());

        Map<String,Integer> houseBookingMap = assignHouseRemainRooms(bookList,queryStartTime,queryEndTime,houseMap); // 每个房间留存房间数量Map<房间id,数量>

        for (House house:houseList) {
            if (house == null)
                continue;

            // 将房间的图片，写入房型对象中
            StringBuilder fileSqlx = new StringBuilder("");
            fileSqlx.append(" and link_id = '").append(house.getId()).append("'");
            List<FileInfo> fileInfoList = fileService.queryList(fileSqlx.toString());
            house.setFileInfoList(fileInfoList);

            // 进行累加数据，计算房型还剩余多少房间
            if (!houseBookingMap.containsKey(Func.parseStr(house.getId()))) {
                house.setRemainRooms(Func.parseStr(house.getNumber()));
                continue;
            }
            int i = Func.parseInt(house.getNumber()) - Func.parseInt(houseBookingMap.get(Func.parseStr(house.getId())));
            house.setRemainRooms(Func.parseStr(i));

        };


        hotel.setHouseList(houseList);
        return hotel;
    }


    /**
     * 在时间区间下进行验证每个房间的剩余数据，取最小数量作为留存房间的数量
     * @param bookList 所有的订单列表
     * @param startDate 查询开始时间
     * @param endDate 查询结束时间
     * @param houseMap  Map<房间id, House>
     * @return Map<房间id,数量>
     */
    public Map assignHouseRemainRooms(List<Booking> bookList, String startDate, String endDate ,Map<String, House> houseMap) {
        if (bookList == null || Func.checkNull(startDate) || Func.checkNull(endDate) || houseMap == null)
            return new HashMap();

        // 将时间统一转化为 yyyy-MM-dd
        String startTime = DateUtil.parseDateToStr((Func.parseDate(startDate)), DateUtil.Time_Formatter_Day);
        String endTime = DateUtil.parseDateToStr((Func.parseDate(endDate)), DateUtil.Time_Formatter_Day);

        Map<String, List<Booking>> bookMap = new HashMap<>(); // map<houseId, liset<Booking>>
        List<Booking> bList = new ArrayList<>();
        for (Booking b :bookList) {
            if (Func.checkNull(b.getHouseId()))
                continue;

            if (bookMap.containsKey(b.getHouseId()))
            {
                bookMap.get(b.getHouseId()).add(b);
                continue;
            }

            bList = new ArrayList<>();
            bList.add(b);
            bookMap.put(b.getHouseId(),bList);
        }

        Set<String> dayQuerySet = new HashSet<>();
        // 遍历查询的每一天当做一个列表数据
        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);
            dayQuerySet.add(time);
        }

        Map<String, Integer> houseBookingMap = new HashMap<>();
        List<Booking> bookHouseList = new ArrayList<>(); // 相同房型的订单汇总
        Map<String, Integer> bookingTimeMap = new HashMap(); // map<时间，天数>进行累加 订单中的房间数量
        String houseId = null; // 房间id
        String timeTemp = null; // 日期 例2023-08-23

        for (Map.Entry<String, List<Booking>> entry : bookMap.entrySet())
        {
            houseId = entry.getKey();
            bookHouseList = entry.getValue(); // 相同房型的订单汇总

            bookingTimeMap = new HashMap(); // map<时间，天数>进行累加 单个房型的订单中房间的数量
            for (Booking booking : bookHouseList) {
                if (Func.checkNull(booking.getHouseId()))
                    continue;

                int day = DateUtil.getDayDiff(booking.getOrderStartTime(), booking.getOrderEndTime());
                for (int i = 0; i < day; i++) {
                    timeTemp = DateUtil.parseDateToStr(DateUtil.addDate(DateUtil.parseDateOnly(booking.getOrderStartTime()), Calendar.DATE, i), DateUtil.Time_Formatter_Day);
                    if (!dayQuerySet.contains(timeTemp)) // 不在查询范围内，不作记录
                        continue;


                    if (!bookingTimeMap.containsKey(timeTemp)) {
                        bookingTimeMap.put(timeTemp, booking.getHouseOrderNumber());
                        continue;
                    }

                    bookingTimeMap.put(timeTemp, booking.getHouseOrderNumber() + Func.parseInt(bookingTimeMap.get(timeTemp)));
                }

                houseBookingMap.put(houseId,getMaxNum(bookingTimeMap));
            }

        }

        return houseBookingMap;
    }

    /**
     * 一个房间的所有日期当中，取单日最大值房间数量，当做留存数
     * @param bookingTimeMap
     * @return
     */
    public Integer getMaxNum(Map<String, Integer> bookingTimeMap)
    {
        if (bookingTimeMap == null || bookingTimeMap.isEmpty())
            return 0;

        List<Integer> numbersTemp = new ArrayList<Integer>(); // 临时数值
        for (Map.Entry<String,Integer> entry : bookingTimeMap.entrySet())
        {
            numbersTemp.add(entry.getValue());
        }

        return numbersTemp.stream ().reduce (Integer::max).get ();// 得到最大值
    }

}
