package com.ruoyi.web.modules.delivery.service.impl;

import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.delivery.constant.DeliveryConstants;
import com.ruoyi.web.modules.delivery.domain.BizShopDeliverySetting;
import com.ruoyi.web.modules.delivery.dto.DeliveryRegionDTO;
import com.ruoyi.web.modules.delivery.dto.ShopDeliverySaveDTO;
import com.ruoyi.web.modules.delivery.mapper.BizShopDeliverySettingMapper;
import com.ruoyi.web.modules.delivery.service.IShopDeliveryService;
import com.ruoyi.web.modules.delivery.vo.DeliveryRegionVO;
import com.ruoyi.web.modules.delivery.vo.ShopDeliverySettingVO;
import com.ruoyi.web.modules.region.domain.BizRegion;
import com.ruoyi.web.modules.region.mapper.BizRegionMapper;

@Service
public class ShopDeliveryServiceImpl implements IShopDeliveryService
{
    @Autowired
    private BizShopDeliverySettingMapper deliverySettingMapper;

    @Autowired
    private BizRegionMapper regionMapper;

    @Override
    public ShopDeliverySettingVO getByShopId(Long shopId)
    {
        BizShopDeliverySetting setting = deliverySettingMapper.selectByShopId(shopId);
        if (setting == null)
        {
            return null;
        }
        return toVo(setting);
    }

    @Override
    public void save(Long shopId, ShopDeliverySaveDTO dto, String operator)
    {
        validate(dto);
        String regionCode = StringUtils.trim(dto.getRegion().getRegionCode());
        RegionSnapshot region = resolveRegionSnapshot(regionCode);
        Date now = new Date();
        BizShopDeliverySetting existing = deliverySettingMapper.selectByShopId(shopId);
        BizShopDeliverySetting row = new BizShopDeliverySetting();
        row.setShopId(shopId);
        row.setShipperName(StringUtils.trim(dto.getShipperName()));
        row.setShipperMobile(StringUtils.trim(dto.getShipperMobile()));
        row.setRegionCode(regionCode);
        row.setRegionName(buildRegionName(region));
        row.setCityName(region.cityName);
        row.setDetailAddress(StringUtils.trim(dto.getDetailAddress()));
        row.setUpdateBy(operator);
        row.setUpdateTime(now);
        if (existing == null)
        {
            row.setCreateBy(operator);
            row.setCreateTime(now);
            deliverySettingMapper.insert(row);
            return;
        }
        deliverySettingMapper.updateByShopId(row);
    }

    private void validate(ShopDeliverySaveDTO dto)
    {
        if (dto == null)
        {
            throw new ServiceException(DeliveryConstants.MSG_SHIPPER_NAME_REQUIRED);
        }
        String shipperName = StringUtils.trim(dto.getShipperName());
        if (StringUtils.isEmpty(shipperName))
        {
            throw new ServiceException(DeliveryConstants.MSG_SHIPPER_NAME_REQUIRED);
        }
        if (shipperName.length() > DeliveryConstants.MAX_SHIPPER_NAME_LENGTH)
        {
            throw new ServiceException(DeliveryConstants.MSG_SHIPPER_NAME_REQUIRED);
        }
        String mobile = StringUtils.trim(dto.getShipperMobile());
        if (StringUtils.isEmpty(mobile) || !mobile.matches("^1\\d{10}$"))
        {
            throw new ServiceException(DeliveryConstants.MSG_SHIPPER_MOBILE_INVALID);
        }
        String detailAddress = StringUtils.trim(dto.getDetailAddress());
        if (StringUtils.isEmpty(detailAddress))
        {
            throw new ServiceException(DeliveryConstants.MSG_DETAIL_ADDRESS_REQUIRED);
        }
        if (detailAddress.length() > DeliveryConstants.MAX_DETAIL_ADDRESS_LENGTH)
        {
            throw new ServiceException(DeliveryConstants.MSG_DETAIL_ADDRESS_REQUIRED);
        }
        DeliveryRegionDTO region = dto.getRegion();
        if (region == null || StringUtils.isEmpty(StringUtils.trim(region.getRegionCode())))
        {
            throw new ServiceException(DeliveryConstants.MSG_REGION_INVALID);
        }
    }

    private RegionSnapshot resolveRegionSnapshot(String regionCode)
    {
        BizRegion district = selectDistrictByCode(regionCode);
        if (district == null)
        {
            throw new ServiceException(DeliveryConstants.MSG_REGION_INVALID);
        }
        BizRegion city = regionMapper.selectById(district.getPid());
        BizRegion province = city == null ? null : regionMapper.selectById(city.getPid());
        if (city == null || province == null
                || !Integer.valueOf(DeliveryConstants.REGION_TYPE_PROVINCE).equals(province.getType())
                || !Integer.valueOf(DeliveryConstants.REGION_TYPE_CITY).equals(city.getType()))
        {
            throw new ServiceException(DeliveryConstants.MSG_REGION_INVALID);
        }
        RegionSnapshot snapshot = new RegionSnapshot();
        snapshot.provinceName = province.getName();
        snapshot.cityName = city.getName();
        snapshot.districtName = district.getName();
        return snapshot;
    }

    private BizRegion selectDistrictByCode(String regionCode)
    {
        try
        {
            BizRegion district = regionMapper.selectByCode(Integer.parseInt(regionCode.trim()));
            if (district == null
                    || !Integer.valueOf(DeliveryConstants.REGION_TYPE_DISTRICT).equals(district.getType()))
            {
                return null;
            }
            return district;
        }
        catch (NumberFormatException ex)
        {
            return null;
        }
    }

    private String buildRegionName(RegionSnapshot region)
    {
        return region.provinceName + DeliveryConstants.REGION_NAME_SEPARATOR + region.cityName
                + DeliveryConstants.REGION_NAME_SEPARATOR + region.districtName;
    }

    private ShopDeliverySettingVO toVo(BizShopDeliverySetting setting)
    {
        ShopDeliverySettingVO vo = new ShopDeliverySettingVO();
        vo.setSettingId(setting.getSettingId());
        vo.setShopId(setting.getShopId());
        vo.setShipperName(setting.getShipperName());
        vo.setShipperMobile(setting.getShipperMobile());
        vo.setRegion(buildRegionVo(setting));
        vo.setDetailAddress(setting.getDetailAddress());
        vo.setUpdateTime(setting.getUpdateTime());
        return vo;
    }

    private DeliveryRegionVO buildRegionVo(BizShopDeliverySetting setting)
    {
        DeliveryRegionVO regionVo = new DeliveryRegionVO();
        regionVo.setRegionCode(setting.getRegionCode());
        fillRegionNames(regionVo, setting.getRegionName());
        fillRegionIds(regionVo, setting.getRegionCode());
        return regionVo;
    }

    private void fillRegionNames(DeliveryRegionVO regionVo, String regionName)
    {
        if (StringUtils.isEmpty(regionName))
        {
            return;
        }
        String[] parts = regionName.split(DeliveryConstants.REGION_NAME_SEPARATOR, 3);
        if (parts.length > 0)
        {
            regionVo.setProvinceName(parts[0]);
        }
        if (parts.length > 1)
        {
            regionVo.setCityName(parts[1]);
        }
        if (parts.length > 2)
        {
            regionVo.setDistrictName(parts[2]);
        }
    }

    private void fillRegionIds(DeliveryRegionVO regionVo, String regionCode)
    {
        BizRegion district = selectDistrictByCode(regionCode);
        if (district == null)
        {
            return;
        }
        regionVo.setDistrictId(district.getId());
        BizRegion city = regionMapper.selectById(district.getPid());
        if (city == null)
        {
            return;
        }
        regionVo.setCityId(city.getId());
        BizRegion province = regionMapper.selectById(city.getPid());
        if (province != null)
        {
            regionVo.setProvinceId(province.getId());
        }
    }

    private static class RegionSnapshot
    {
        private String provinceName;

        private String cityName;

        private String districtName;
    }
}
