package com.ylx.address.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.utils.StringUtils;
import com.ylx.massage.domain.dto.CoordinateDTO;
import com.ylx.massage.domain.vo.CityInfoVo;
import com.ylx.massage.domain.vo.MerchantCurrentAddressVO;
import com.ylx.massage.domain.vo.UserAddressListVO;
import com.ylx.area.service.AreaService;
import com.ylx.address.domain.dto.UserAddressAddDto;
import com.ylx.address.domain.dto.UserAddressDeleteDto;
import com.ylx.address.domain.dto.UserAddressDto;
import com.ylx.address.domain.dto.UserAddressUpdateDto;
import com.ylx.address.domain.vo.UserAddressVo;
import com.ylx.address.mapper.TAddressMapper;
import com.ylx.address.domain.TAddress;
import com.ylx.address.service.TAddressService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 轮播图(TAddress)表服务实现类
 *
 * @author makejava
 * @since 2024-04-11 17:18:53
 */
@Service("tAddressService")
@Slf4j
public class TAddressServiceImpl extends ServiceImpl<TAddressMapper, TAddress> implements TAddressService {

    //0=未删除
    private static final Integer NO_DELETE = 0;
    //1=用户
    private static final Integer USER_TYPE = 1;
    //2=商户
    private static final Integer MERCHANT_USER_TYPE = 2;
    //1=真实地址
    private static final Integer TYPE = 1;
    //1=默认地址
    private static final Integer IS_DEFAULT = 1;
    //0=不是默认地址
    private static final Integer NO_DEFAULT = 0;
    @Autowired
    private AreaService areaService;


    @Override
    public TAddress getByOpenId(String openId) {
        LambdaQueryWrapper<TAddress> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        objectLambdaQueryWrapper.eq(TAddress::getOpenid, openId).eq(TAddress::getType, 1);
        return this.getOne(objectLambdaQueryWrapper);
    }


    private List<TAddress> getAddressList(String openId, Integer userType,String cityCode) {
        LambdaQueryWrapper<TAddress> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        objectLambdaQueryWrapper.eq(TAddress::getOpenid, openId)
                .eq(TAddress::getUserType, userType)
                // cityCode不为null才添加eq条件
                .and(StrUtil.isNotBlank(cityCode), w -> w.eq(TAddress::getCityCode, cityCode))
                .eq(TAddress::getIsDelete,0)
                .orderByDesc(TAddress::getCreateTime);
        return this.list(objectLambdaQueryWrapper);
    }
    /**
     *  根据openId和userType获取地址列表 用户类型（1：用户 2：商户）
     * @param dto
     * @return
     */
    @Override
    public List<UserAddressVo> getByOpenIdList(UserAddressDto dto) {
        List<TAddress> addressList = getAddressList(dto.getOpenId(), 1,dto.getCityCode());
        if (CollectionUtils.isEmpty(addressList)) {
            return Collections.emptyList();
        }
        return addressList.stream().map(this::convertToVo).collect(Collectors.toList());
    }

    @Override
    public List<UserAddressListVO> getPcUserAddressList(String openId) {
        return this.baseMapper.selectPcUserAddressList(openId);
    }

    @Override
    public MerchantCurrentAddressVO getCurrentMerchantAddress(Integer merchantId) {
        if (Objects.isNull(merchantId)) {
            throw new RuntimeException("商户id不能为空");
        }
        return this.baseMapper.selectCurrentMerchantRealAddress(merchantId);
    }

    private UserAddressVo convertToVo(TAddress address) {
        UserAddressVo vo = new UserAddressVo();
        BeanUtils.copyProperties(address, vo);
        return vo;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean defaultAddress(TAddress tAddress) {
        if (StringUtils.isBlank(tAddress.getOpenid())) {
            throw new RuntimeException("openid不能为空");
        }
        // 查询默认地址
        TAddress oldAddress = this.getByOpenId(tAddress.getOpenid());
        if (oldAddress != null) {
            oldAddress.setType(0);
            this.updateById(oldAddress);
        }
        tAddress.setType(1);
        return this.updateById(tAddress);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object insertAddress(TAddress tAddress) {
        if (Objects.isNull(tAddress)) {
            throw new RuntimeException("地址信息不能为空");
        }
        if (Objects.isNull(tAddress.getMerchantId())) {
            throw new RuntimeException("商户id不能为空");
        }
        if (StringUtils.isBlank(tAddress.getAddress())) {
            throw new RuntimeException("地址不能为空");
        }
        if (Objects.isNull(tAddress.getLongitude())) {
            throw new RuntimeException("经度不能为空");
        }
        if (Objects.isNull(tAddress.getLatitude())) {
            throw new RuntimeException("纬度不能为空");
        }

        TAddress oldDefaultAddress = this.getMerchantDefaultAddress(tAddress.getMerchantId());
        boolean setAsDefault = oldDefaultAddress == null || IS_DEFAULT.equals(tAddress.getIsDefault());
        fillMerchantAddressDefaults(tAddress, setAsDefault);

        if (oldDefaultAddress != null && IS_DEFAULT.equals(tAddress.getIsDefault())) {
            oldDefaultAddress.setIsDefault(NO_DEFAULT);
            this.updateById(oldDefaultAddress);
        }
        return this.save(tAddress);
    }

    /**
     * 获取商户默认地址
     *
     * @param merchantId
     * @return TAddress
     */
    private TAddress getMerchantDefaultAddress(Long merchantId) {
        return this.getOne(new LambdaQueryWrapper<TAddress>()
                .eq(TAddress::getMerchantId, merchantId)
                .eq(TAddress::getUserType, MERCHANT_USER_TYPE)
                .eq(TAddress::getType, TYPE)
                .eq(TAddress::getIsDelete, NO_DELETE)
                .eq(TAddress::getIsDefault, IS_DEFAULT)
                .last("limit 1"));
    }

    private void fillMerchantAddressDefaults(TAddress tAddress, boolean setAsDefault) {
        tAddress.setUserType(MERCHANT_USER_TYPE);
        tAddress.setType(TYPE);
        tAddress.setIsDelete(NO_DELETE);
        tAddress.setIsDefault(setAsDefault ? IS_DEFAULT : NO_DEFAULT);
        if (StringUtils.isBlank(tAddress.getDetailAddress())) {
            String detailAddress = tAddress.getAddress();
            if (StringUtils.isNotBlank(tAddress.getRoomNumber())) {
                detailAddress = detailAddress + " " + tAddress.getRoomNumber();
            }
            tAddress.setDetailAddress(detailAddress);
        }
        if (StringUtils.isBlank(tAddress.getCityCode())) {
            CoordinateDTO dto = new CoordinateDTO();
            dto.setLongitude(tAddress.getLongitude());
            dto.setLatitude(tAddress.getLatitude());
            CityInfoVo cityInfoVo = areaService.getCityInfoByCoordinates(dto);
            if (cityInfoVo != null && StringUtils.isNotBlank(cityInfoVo.getCityCode())) {
                tAddress.setCityCode(cityInfoVo.getCityCode());
            }
        }
    }

     @Override
    @Transactional(rollbackFor = Exception.class)
    public Object insertVirtualAddress(TAddress tAddress) {
        if (StringUtils.isBlank(tAddress.getOpenid())) {
            throw new RuntimeException("openid不能为空");
        }
        //检查用户类型是否为空
        if (Objects.isNull(tAddress.getUserType())) {
            throw new RuntimeException("用户类型不能为空");
        }
        //检查用户类型是否为1或2
        if (tAddress.getUserType() != 1 && tAddress.getUserType() != 2) {
            throw new RuntimeException("用户类型只能为1或2");
        }
        //检查用户类型是否正确
         if (tAddress.getUserType() != 2) {
             throw new RuntimeException("用户类型错误，用户类型只能为2");
         }

         //检查地址类型是否为空
         if (Objects.isNull(tAddress.getType())) {
             throw new RuntimeException("地址类型不能为空");
         }
         //检查地址类型是否为1或2
         if (tAddress.getType() != 2) {
             throw new RuntimeException("地址类型错误，地址类型只能为2");
         }
         if(StringUtils.isBlank(tAddress.getCityCode())){
             CoordinateDTO dto = new CoordinateDTO();
             dto.setLongitude(tAddress.getLongitude());
             dto.setLatitude(tAddress.getLatitude());
             CityInfoVo cityInfoVo = areaService.getCityInfoByCoordinates(dto);
             log.info("根据经纬度获取城市信息：{}", JSON.toJSONString(cityInfoVo));
             tAddress.setCityCode(cityInfoVo.getCityCode());
         }
         if (StringUtils.isBlank(tAddress.getDetailAddress())){
             tAddress.setDetailAddress(tAddress.getAddress());
         }
        return this.save(tAddress);
    }

    @Override
    public Object updateAddress(TAddress tAddress) {
        if (StringUtils.isBlank(tAddress.getOpenid())) {
            throw new RuntimeException("openid不能为空");
        }
        if (StringUtils.isBlank(tAddress.getId())) {
            throw new RuntimeException("地址id不能为空");
        }
        //查询默认地址
        TAddress oldAddress = this.getByOpenId(tAddress.getOpenid());
        tAddress.setType(1);
        if (oldAddress != null && !oldAddress.getId().equals(tAddress.getId())) {
            tAddress.setType(0);
        }
        return this.updateById(tAddress);
    }

    /**
     * 用户端新增地址
     * @param dto
     */
    @Override
    public void addUserAddress(UserAddressAddDto dto) {


        // 1. DTO -> 实体 转换
        TAddress address = new TAddress();
        BeanUtil.copyProperties(dto, address);

        // 2. 补充实体中缺失但需要入库的字段
        address.setIsDelete(NO_DELETE);
        address.setUserType(USER_TYPE);
        address.setType(TYPE);
        address.setDetailAddress(address.getAddress() + " " + address.getRoomNumber());


        // 3. 处理默认地址逻辑
        // 如果当前新增的地址是默认地址，需要先将该用户下的其他地址设为非默认
        if (IS_DEFAULT.equals(dto.getIsDefault())) {
            LambdaQueryWrapper<TAddress> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TAddress::getUserId, dto.getUserId())
                    .eq(TAddress::getIsDefault, IS_DEFAULT);
            TAddress defaultExists = this.baseMapper.selectOne(wrapper);
            if (defaultExists != null) {
                defaultExists.setIsDefault(NO_DEFAULT);
                this.updateById(defaultExists);
            }
        }

        // 5. 执行入库
        this.baseMapper.insert(address);
    }

    /**
     * 用户端更新地址
     * @param dto
     */
    @Override
    public void updateUserAddress(UserAddressUpdateDto dto) {
        // 1. 参数校验：地址ID不能为空
        if (StrUtil.isBlank(dto.getId())) {
            throw new RuntimeException("地址ID不能为空");
        }

        // 2. 查询原有地址记录
        TAddress existingAddress = this.baseMapper.selectById(dto.getId());
        if (existingAddress == null) {
            throw new RuntimeException("地址不存在");
        }

        // 3. 权限校验：只能修改自己的地址
        if (!existingAddress.getUserId().equals(dto.getUserId())) {
            throw new RuntimeException("无权修改该地址");
        }
        // 4. 将DTO中非空字段拷贝到实体（忽略为null的字段）
        BeanUtil.copyProperties(dto, existingAddress, "id", "userId", "openid", "merchantId",
                "userType", "type", "createTime", "isDelete");

        // 6. 拼接详细地址（address + 空格 + roomNumber）
        String detailAddress = "";
        if (StrUtil.isNotBlank(existingAddress.getAddress())
                && StrUtil.isNotBlank(existingAddress.getRoomNumber())) {
            detailAddress = existingAddress.getAddress() + " " + existingAddress.getRoomNumber();
        } else if (StrUtil.isNotBlank(existingAddress.getAddress())) {
            detailAddress = existingAddress.getAddress();
        } else if (StrUtil.isNotBlank(existingAddress.getRoomNumber())) {
            detailAddress = existingAddress.getRoomNumber();
        }
        existingAddress.setDetailAddress(detailAddress);

        // 8. 执行更新（根据ID更新）
        int rows = this.baseMapper.updateById(existingAddress);
        if (rows != 1) {
            throw new RuntimeException("更新地址失败");
        }
    }

    /**
     * 用户端删除地址
     * @param dto
     */
    @Override
    public void deleteUserAddress(UserAddressDeleteDto dto) {
        String addressId = dto.getId();

        // 1. 查询地址是否存在且未被删除
        TAddress address = this.baseMapper.selectOne(
                new LambdaQueryWrapper<TAddress>()
                        .eq(TAddress::getId, addressId)
                        .eq(TAddress::getIsDelete, 0)
        );
        if (address == null) {
            throw new RuntimeException("地址不存在或已被删除");
        }


        // 2. 权限校验：只能删除自己的地址
        if (!address.getUserId().equals(dto.getUserId())) {
            throw new RuntimeException("无权删除该地址");
        }

        // 3. 执行逻辑删除（MyBatis-Plus 会自动将 isDelete 设为 1，并更新 updateTime）
        int rows = this.baseMapper.deleteById(addressId);
        if (rows != 1) {
            throw new RuntimeException("删除地址失败");
        }

        // 4. 【可选】如果删除的是默认地址，将用户的其他最新地址设为默认
        if (IS_DEFAULT.equals(address.getIsDefault())) {
            // 查询该用户下未被删除的其他地址，按创建时间倒序取第一条
            LambdaQueryWrapper<TAddress> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TAddress::getUserId, dto.getUserId())
                    .eq(TAddress::getIsDelete, 0)
                    .orderByDesc(TAddress::getCreateTime)
                    .last("limit 1");
            TAddress newDefault = this.baseMapper.selectOne(wrapper);
            if (newDefault != null) {
                newDefault.setIsDefault(IS_DEFAULT);
                this.baseMapper.updateById(newDefault);
            }
        }
    }

}

