package com.jeeplus.hotelorder.room.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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeeplus.core.query.QueryWrapperGenerator;
import com.jeeplus.hotelorder.room.domain.HotelRoom;
import com.jeeplus.hotelorder.room.domain.HotelRoomType;
import com.jeeplus.hotelorder.room.mapper.HotelRoomMapper;
import com.jeeplus.hotelorder.utils.QrCodeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 酒店房间服务类
 * @author jeeplus
 */
@Service
public class HotelRoomService extends ServiceImpl<HotelRoomMapper, HotelRoom> {

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

    @Resource
    private HotelRoomMapper hotelRoomMapper;

    @Resource
    private HotelRoomTypeService hotelRoomTypeService;

    /** 二维码基础域名（生产环境配置到Nacos） */
    @Value("${hotel.qr.base-url:https://hotel.example.com}")
    private String qrBaseUrl;

    /**
     * 分页查询房间列表
     * 利用@Query注解自动构建查询条件
     * @param page 分页参数
     * @param hotelRoom 查询条件
     * @return 分页结果
     * @throws Exception 查询异常
     */
    public IPage<HotelRoom> findPage(Page<HotelRoom> page, HotelRoom hotelRoom) throws Exception {
        QueryWrapper<HotelRoom> queryWrapper = QueryWrapperGenerator.buildQueryCondition(hotelRoom, HotelRoom.class);
        queryWrapper.eq("del_flag", 0);
        queryWrapper.orderByAsc("floor").orderByAsc("room_no");
        IPage<HotelRoom> result = hotelRoomMapper.selectPage(page, queryWrapper);
        // 填充房间类型名称
        fillRoomTypeName(result.getRecords());
        return result;
    }

    /**
     * 根据ID查询房间详情
     * @param id 房间ID
     * @return 房间信息
     */
    public HotelRoom queryById(String id) {
        HotelRoom room = hotelRoomMapper.selectById(id);
        if (room != null) {
            fillRoomTypeName(java.util.Collections.singletonList(room));
        }
        return room;
    }

    /**
     * 根据房间号查询房间（用于扫码入口）
     * @param roomNo 房间号
     * @return 房间信息
     */
    public HotelRoom getByRoomNo(String roomNo) {
        QueryWrapper<HotelRoom> qw = new QueryWrapper<>();
        qw.eq("room_no", roomNo);
        qw.eq("del_flag", 0);
        qw.last("LIMIT 1");
        HotelRoom room = hotelRoomMapper.selectOne(qw);
        if (room != null) {
            fillRoomTypeName(java.util.Collections.singletonList(room));
        }
        return room;
    }

    /**
     * 校验房间号是否已存在
     * @param roomNo 房间号
     * @param excludeId 排除的房间ID（编辑时传入）
     * @return true-已存在, false-不存在
     */
    public boolean existsByRoomNo(String roomNo, String excludeId) {
        QueryWrapper<HotelRoom> qw = new QueryWrapper<>();
        qw.eq("room_no", roomNo);
        qw.eq("del_flag", 0);
        if (StringUtils.isNotBlank(excludeId)) {
            qw.ne("id", excludeId);
        }
        return hotelRoomMapper.selectCount(qw) > 0;
    }

    /**
     * 新增/编辑房间
     * 新增时自动生成二维码，编辑时不改变二维码
     * @param hotelRoom 房间信息
     * @return 操作结果消息
     * @throws Exception 业务异常
     */
    @Transactional(rollbackFor = Exception.class)
    public String saveRoom(HotelRoom hotelRoom) throws Exception {
        // 校验房间号唯一性
        if (existsByRoomNo(hotelRoom.getRoomNo(), hotelRoom.getId())) {
            throw new RuntimeException("房间号【" + hotelRoom.getRoomNo() + "】已存在");
        }

        if (StringUtils.isBlank(hotelRoom.getId())) {
            // 新增房间
            hotelRoom.setId(UUID.randomUUID().toString().replace("-", ""));
            hotelRoom.setDelFlag(0);
            if (StringUtils.isBlank(hotelRoom.getStatus())) {
                hotelRoom.setStatus("0"); // 默认正常状态
            }
            // 生成房间短码
            hotelRoom.setRoomShortCode(generateShortCode(hotelRoom.getRoomNo()));
            // 自动生成二维码
            generateQrCode(hotelRoom);
            hotelRoomMapper.insert(hotelRoom);
        } else {
            // 编辑房间（不改变二维码）
            hotelRoomMapper.updateById(hotelRoom);
        }
        return "操作成功";
    }

    /**
     * 切换房间状态（正常↔暂停停用）
     * @param id 房间ID
     * @param status 目标状态
     * @return 操作结果消息
     */
    @Transactional(rollbackFor = Exception.class)
    public String toggleStatus(String id, String status) {
        HotelRoom room = hotelRoomMapper.selectById(id);
        if (room == null) {
            throw new RuntimeException("房间不存在");
        }
        room.setStatus(status);
        hotelRoomMapper.updateById(room);
        return "操作成功";
    }

    /**
     * 补打二维码（内容不变，重新生成图片）
     * @param id 房间ID
     * @return 二维码Base64图片
     * @throws Exception 生成异常
     */
    public String reprintQrCode(String id) throws Exception {
        HotelRoom room = hotelRoomMapper.selectById(id);
        if (room == null) {
            throw new RuntimeException("房间不存在");
        }
        if (StringUtils.isBlank(room.getQrCodeUrl())) {
            throw new RuntimeException("该房间尚未生成二维码");
        }
        // 使用已有的URL重新生成图片
        String base64Image = QrCodeUtils.generateQrCodeBase64(room.getQrCodeUrl());
        room.setQrCodeImage(base64Image);
        hotelRoomMapper.updateById(room);
        return base64Image;
    }

    /**
     * 重新生成二维码（内容改变，旧码废弃）
     * @param id 房间ID
     * @return 新的二维码Base64图片
     * @throws Exception 生成异常
     */
    @Transactional(rollbackFor = Exception.class)
    public String regenerateQrCode(String id) throws Exception {
        HotelRoom room = hotelRoomMapper.selectById(id);
        if (room == null) {
            throw new RuntimeException("房间不存在");
        }
        // 重新生成二维码
        generateQrCode(room);
        hotelRoomMapper.updateById(room);
        return room.getQrCodeImage();
    }

    /**
     * 删除房间（逻辑删除）
     * @param id 房间ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoom(String id) {
        hotelRoomMapper.deleteById(id);
    }

    /**
     * 批量删除房间
     * @param ids 房间ID，逗号分隔
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(String ids) {
        String[] idArray = ids.split(",");
        for (String id : idArray) {
            hotelRoomMapper.deleteById(id.trim());
        }
    }

    /**
     * 为房间生成二维码
     * 包含：构建URL → 生成签名 → 生成图片 → 设置到实体
     * @param room 房间实体
     * @throws Exception 生成异常
     */
    private void generateQrCode(HotelRoom room) throws Exception {
        long timestamp = System.currentTimeMillis();
        // 构建二维码URL
        String qrUrl = QrCodeUtils.buildQrCodeUrl(
                qrBaseUrl,
                room.getRoomShortCode(),
                room.getId(),
                room.getRoomNo(),
                timestamp
        );
        // 生成签名
        String sign = QrCodeUtils.generateSign(room.getId(), room.getRoomNo(), timestamp);
        // 生成二维码图片（Base64）
        String base64Image = QrCodeUtils.generateQrCodeBase64(qrUrl);

        room.setQrCodeUrl(qrUrl);
        room.setQrCodeImage(base64Image);
        room.setQrCodeSign(sign);
        room.setQrGeneratedTime(new java.util.Date());
    }

    /**
     * 根据房间号生成短码
     * 使用房间号的Base62编码，保持URL简短
     * @param roomNo 房间号
     * @return 短码
     */
    private String generateShortCode(String roomNo) {
        // 简单方案：直接使用房间号作为短码（如 "808" → "808"）
        // 如需更短可使用Base62编码
        return roomNo;
    }

    /**
     * 批量填充房间类型名称
     */
    private void fillRoomTypeName(java.util.List<HotelRoom> rooms) {
        if (rooms == null || rooms.isEmpty()) {
            return;
        }
        // 收集所有类型ID
        java.util.Set<String> typeIds = new java.util.HashSet<>();
        for (HotelRoom room : rooms) {
            if (StringUtils.isNotBlank(room.getRoomTypeId())) {
                typeIds.add(room.getRoomTypeId());
            }
        }
        if (typeIds.isEmpty()) {
            return;
        }
        // 批量查询类型
        QueryWrapper<HotelRoomType> qw = new QueryWrapper<>();
        qw.in("id", typeIds);
        java.util.List<HotelRoomType> types = hotelRoomTypeService.list(qw);
        java.util.Map<String, String> typeNameMap = new java.util.HashMap<>();
        for (HotelRoomType type : types) {
            typeNameMap.put(type.getId(), type.getName());
        }
        // 填充名称
        for (HotelRoom room : rooms) {
            if (StringUtils.isNotBlank(room.getRoomTypeId())) {
                room.setRoomTypeName(typeNameMap.get(room.getRoomTypeId()));
            }
        }
    }
}
