package cn.nianxx.thhotel.platform.hotel.repository;

import cn.nianxx.thhotel.platform.hotel.common.enums.PlatformHotelStatus;
import cn.nianxx.thhotel.platform.hotel.domain.PlatformHotelEntity;
import cn.nianxx.thhotel.platform.hotel.domain.PlatformUserHotelEntity;
import cn.nianxx.thhotel.platform.hotel.mapper.PlatformHotelMapper;
import cn.nianxx.thhotel.platform.hotel.mapper.PlatformUserHotelMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;

/**
 * 基于 MyBatis-Plus 的平台酒店仓储实现。
 */
@Repository
public class MybatisPlatformHotelRepository implements PlatformHotelRepository {

    private final PlatformHotelMapper hotelMapper;
    private final PlatformUserHotelMapper userHotelMapper;

    public MybatisPlatformHotelRepository(
            PlatformHotelMapper hotelMapper,
            PlatformUserHotelMapper userHotelMapper) {
        this.hotelMapper = hotelMapper;
        this.userHotelMapper = userHotelMapper;
    }

    @Override
    public Optional<PlatformHotelEntity> findHotelByHotelId(String hotelId) {
        return Optional.ofNullable(hotelMapper.selectOne(Wrappers.<PlatformHotelEntity>lambdaQuery()
                .eq(PlatformHotelEntity::getHotelId, hotelId)
                .last("LIMIT 1")));
    }

    @Override
    public List<PlatformHotelEntity> listActiveHotels() {
        return hotelMapper.selectList(Wrappers.<PlatformHotelEntity>lambdaQuery()
                .eq(PlatformHotelEntity::getHotelStatus, PlatformHotelStatus.ACTIVE.name())
                .orderByAsc(PlatformHotelEntity::getSortOrder)
                .orderByAsc(PlatformHotelEntity::getHotelId));
    }

    @Override
    public List<String> listUserHotelIds(Long userId) {
        return userHotelMapper.selectList(Wrappers.<PlatformUserHotelEntity>lambdaQuery()
                        .eq(PlatformUserHotelEntity::getUserId, userId)
                        .orderByDesc(PlatformUserHotelEntity::getDefaultHotel)
                        .orderByAsc(PlatformUserHotelEntity::getHotelId))
                .stream()
                .map(PlatformUserHotelEntity::getHotelId)
                .toList();
    }

    @Override
    public Optional<String> findUserDefaultHotelId(Long userId) {
        return Optional.ofNullable(userHotelMapper.selectOne(Wrappers.<PlatformUserHotelEntity>lambdaQuery()
                        .eq(PlatformUserHotelEntity::getUserId, userId)
                        .eq(PlatformUserHotelEntity::getDefaultHotel, true)
                        .last("LIMIT 1")))
                .map(PlatformUserHotelEntity::getHotelId);
    }

    @Override
    public void insertHotel(PlatformHotelEntity hotel) {
        hotelMapper.insert(hotel);
    }

    @Override
    public void updateHotel(PlatformHotelEntity hotel) {
        hotelMapper.updateById(hotel);
    }

    @Override
    public void ensureUserHotel(Long userId, String hotelId, boolean defaultHotel) {
        PlatformUserHotelEntity existing = userHotelMapper.selectOne(Wrappers.<PlatformUserHotelEntity>lambdaQuery()
                .eq(PlatformUserHotelEntity::getUserId, userId)
                .eq(PlatformUserHotelEntity::getHotelId, hotelId)
                .last("LIMIT 1"));
        if (existing != null) {
            if (defaultHotel && !Boolean.TRUE.equals(existing.getDefaultHotel())) {
                existing.setDefaultHotel(true);
                userHotelMapper.updateById(existing);
            }
            return;
        }
        PlatformUserHotelEntity relation = new PlatformUserHotelEntity();
        relation.setUserId(userId);
        relation.setHotelId(hotelId);
        relation.setDefaultHotel(defaultHotel);
        relation.setCreatedAt(nowUtc());
        userHotelMapper.insert(relation);
    }

    private LocalDateTime nowUtc() {
        return LocalDateTime.now(ZoneOffset.UTC);
    }
}
