package com.cyl.manager.staff.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.lang.generator.UUIDGenerator;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyl.config.AESForWeixinGetPhoneNumber;
import com.cyl.external.WechatUtil;
import com.cyl.h5.pojo.dto.H5LoginDTO;
import com.cyl.h5.pojo.dto.MemberAddressDTO;
import com.cyl.h5.pojo.request.*;
import com.cyl.h5.pojo.response.H5LoginResponse;
import com.cyl.h5.pojo.vo.StaffAnswerRecordVO;
import com.cyl.h5.pojo.vo.StaffServiceRecordVO;
import com.cyl.h5.service.H5MemberAddressService;
import com.cyl.manager.staff.domain.*;
import com.cyl.manager.staff.domain.vo.StaffVO;
import com.cyl.manager.staff.mapper.StaffMapper;
import com.cyl.manager.staff.mapper.StaffWechatMapper;
import com.cyl.manager.staff.service.IStaffAnswerRecordService;
import com.cyl.manager.staff.service.IStaffService;
import com.cyl.manager.staff.service.IStaffServiceRecordService;
import com.cyl.manager.ums.domain.MemberAddress;
import com.cyl.manager.ums.domain.MemberLogininfor;
import com.cyl.manager.ums.mapper.MemberAddressMapper;
import com.cyl.manager.ums.mapper.MemberLogininforMapper;
import com.cyl.manager.ums.pojo.vo.MemberAddressVO;
import com.cyl.manager.ums.service.MemberAddressService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginMember;
import com.ruoyi.common.enums.StaffAuthenticateStatusEnum;
import com.ruoyi.common.enums.StaffBondStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.AesCryptoUtils;
import com.ruoyi.common.utils.PhoneUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.config.LocalDataUtil;
import com.ruoyi.framework.web.service.TokenService;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.retry.RetryException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 人员信息Service业务层处理
 *
 * @author ruoyi
 * @date 2023-12-26
 */
@Service
@Slf4j
public class StaffServiceImpl extends ServiceImpl<StaffMapper, Staff> implements IStaffService {
    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private StaffWechatMapper staffWechatMapper;

    @Autowired
    private StaffImageServiceImpl staffImageService;

    @Autowired
    private IStaffServiceRecordService staffServiceRecordService;


    @Autowired
    private H5MemberAddressService h5MemberAddressService;

    @Autowired
    private TokenService tokenService;

    @Value("${aes.key}")
    private String aesKey;

    @Autowired
    private MemberLogininforMapper memberLogininforMapper;

    @Autowired
    private IStaffAnswerRecordService staffAnswerRecordService;

    @Autowired
    private MemberAddressMapper memberAddressMapper;

    /**
     * 查询人员信息
     *
     * @param id 人员信息主键
     * @return 人员信息
     */
    @Override
    public Staff selectStaffById(Long id) {
        return staffMapper.selectStaffById(id);
    }

    /**
     * 查询人员信息列表
     *
     * @param staff 人员信息
     * @return 人员信息
     */
    @Override
    public List<Staff> selectStaffList(Staff staff) {
        return staffMapper.selectStaffList(staff);
    }

    /**
     * 新增人员信息
     *
     * @param staff 人员信息
     * @return 结果
     */
    @Override
    public int insertStaff(Staff staff) {
        staff.setCreateTime(LocalDateTime.now());
        return staffMapper.insertStaff(staff);
    }

    /**
     * 修改人员信息
     *
     * @param staff 人员信息
     * @return 结果
     */
    @Override
    public int updateStaff(Staff staff) {
        staff.setUpdateTime(LocalDateTime.now());
        return staffMapper.updateStaff(staff);
    }

    /**
     * 批量删除人员信息
     *
     * @param ids 需要删除的人员信息主键
     * @return 结果
     */
    @Override
    public int deleteStaffByIds(Long[] ids) {
        return staffMapper.deleteStaffByIds(ids);
    }

    /**
     * 删除人员信息信息
     *
     * @param id 人员信息主键
     * @return 结果
     */
    @Override
    public int deleteStaffById(Long id) {
        return staffMapper.deleteStaffById(id);
    }

    @Override
    public StaffVO selectStaffByIdForFront(Long id) {
        final BeanCopier beanCopier = BeanCopier.create(Staff.class, StaffVO.class, false);
        Staff staff = staffMapper.selectStaffById(id);
        StaffVO staffVo = new StaffVO();
        beanCopier.copy(staff, staffVo, null);
        StaffImage staffImage = new StaffImage();
        staffImage.setStaffId(id);
        List<StaffImage> staffImageList = staffImageService.selectStaffImageList(staffImage);
        if (staffImageList != null && staffImageList.size() > 0) {
            staffVo.setStaffImages(staffImageList);
        }

        //获取服务记录
        List<StaffServiceRecordVO> serviceRecords = staffServiceRecordService.getServiceRecords(id);
        staffVo.setServiceRecords(serviceRecords);

        return staffVo;
    }

    @Override
    public List<StaffVO> selectStaffListForFont(Staff staff) {
        final BeanCopier beanCopier = BeanCopier.create(Staff.class, StaffVO.class, false);
        List<Staff> staffList = staffMapper.selectStaffList(staff);
        List<StaffVO> staffVoList = new ArrayList<>();

        staffList.forEach(staff2 -> {
            StaffVO staffVo = new StaffVO();
            beanCopier.copy(staff2, staffVo, null);
            StaffImage staffImage = new StaffImage();
            staffImage.setStaffId(staff2.getId());
            List<StaffImage> staffImageList = staffImageService.selectStaffImageList(staffImage);
            if (staffImageList != null && staffImageList.size() > 0) {
                staffVo.setStaffImages(staffImageList);
            }

            staffVoList.add(staffVo);
        });

        return staffVoList;
    }

    @Override
    public List<StaffVO> selectStaffListByCondition(Staff staff) {
        StaffListRequest staffListRequest = (StaffListRequest) staff;

        String[] addressArray = parseAddress(staff.getAddress());
        if(addressArray == null){
            throw new RuntimeException("地址格式不正确");
        }

        MemberAddressDTO memberAddressDTO = new MemberAddressDTO();
        memberAddressDTO.setProvince(addressArray[0]);
        memberAddressDTO.setCity(addressArray[1]);
        memberAddressDTO.setDistrict(addressArray[2]);
        List<Long> staffIds = h5MemberAddressService.selectByCondition(memberAddressDTO);

        if(CollectionUtils.isEmpty(staffIds)){
            return new ArrayList<>();
        }

        final BeanCopier beanCopier = BeanCopier.create(Staff.class, StaffVO.class, false);

        List<Staff> staffList = staffMapper.selectStaffByCondition(staffListRequest.getPetTypes(),staffListRequest.getStaffName(),staffIds);
        List<StaffVO> staffVoList = new ArrayList<>();
        staffList.forEach(staff2 -> {
            StaffVO staffVo = new StaffVO();
            beanCopier.copy(staff2, staffVo, null);
            StaffImage staffImage = new StaffImage();
            staffImage.setStaffId(staff2.getId());
            List<StaffImage> staffImageList = staffImageService.selectStaffImageList(staffImage);
            if (staffImageList != null && staffImageList.size() > 0) {
                staffVo.setStaffImages(staffImageList);
            }

            staffVoList.add(staffVo);
        });

        return staffVoList;
    }

    @Override
    public H5LoginResponse wechatLogin(H5LoginDTO params) {
        String openId = params.getOpenId();
        String sessionKey = params.getSessionKey();
        //解密手机号
        String mobile = getMobile(sessionKey, params.getKey(), params.getData());
        if (StringUtils.isEmpty(mobile)) {
            throw new RuntimeException("登录异常");
        }
        Staff staff = createOrUpdateStaff(openId, mobile, null);
        return getLoginResponse(staff.getId());
    }

    private String getMobile(String sessionKey, String key, String data) {
        AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(data, sessionKey, key);
        JSONObject decrypt = aes.decrypt();
        if (decrypt != null) {
            return decrypt.getString("phoneNumber");
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Staff createOrUpdateStaff(String openId, String mobile, String wechatId) {
        //openid为唯一标识，先查询该微信号是否下过单
        LambdaQueryWrapper<StaffWechat> staffWechatWrapper = Wrappers.lambdaQuery(StaffWechat.class);
        staffWechatWrapper.eq(StaffWechat::getRoutineOpenid, openId);
        StaffWechat staffWechatExist = staffWechatMapper.selectOne(staffWechatWrapper);
        Staff staff = null;
        if (staffWechatExist != null) {
            staff = staffMapper.selectById(staffWechatExist.getStaffId());
        } else {
            //查会员
            QueryWrapper<Staff> qw = new QueryWrapper<>();
            qw.eq("phone_encrypted", AesCryptoUtils.encrypt(aesKey, mobile));
            staff = staffMapper.selectOne(qw);
        }

        if (staff == null) {
            //新员工，注册并登录
            staff = new Staff();
            staff.setName("用户" + mobile.substring(7, 11));
            staff.setShortDescription("");
            staff.setPhoneEncrypted(AesCryptoUtils.encrypt(aesKey, mobile));
            staff.setPhone(mobile);
            staff.setPhoneHidden(PhoneUtils.hidePhone(mobile));
            staff.setNickName("用户" + mobile.substring(7, 11));
            staff.setGender(0L);
            staff.setCreateTime(LocalDateTime.now());
            staff.setInviteCode(UUID.randomUUID().toString(true));
            int rows = staffMapper.insert(staff);
            if (rows < 1) {
                throw new RuntimeException("注册失败，请重试");
            }
            if (wechatId == null) {
                StaffWechat staffWechat = new StaffWechat();
                staffWechat.setStaffId(staff.getId());
                staffWechat.setRoutineOpenid(openId);
                staffWechat.setWechatId(wechatId);
                staffWechat.setCreateTime(LocalDateTime.now());
                staffWechat.setCreateBy(staff.getId());
                rows = staffWechatMapper.insert(staffWechat);
                if (rows < 1) {
                    throw new RuntimeException("注册失败，请重试");
                }
            }
        } else {
            QueryWrapper<StaffWechat> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("staff_id", staff.getId());
            StaffWechat staffWechat = staffWechatMapper.selectOne(queryWrapper);
            if (StringUtils.isEmpty(staffWechat.getRoutineOpenid())) {
                staffWechat.setRoutineOpenid(openId);
                staffWechat.setWechatId(wechatId);
                staffWechatMapper.updateById(staffWechat);
            }
        }
        return staff;
    }


    @Transactional(rollbackFor = Throwable.class)
    public H5LoginResponse getLoginResponse(Long staffId) {
        LoginMember loginMember = new LoginMember();
        loginMember.setMemberId(staffId);
        loginMember.setSourceType(1);
        String token = tokenService.createMemberToken(loginMember);
        //record登录
        this.insert(staffId);
        H5LoginResponse response = new H5LoginResponse();
        response.setToken(token);
        return response;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Staff getPhoneAndRegister(String code, String openId) {
        String phone = (String) WechatUtil.getPhoneNumber(code, 1);
        Staff staff = this.createOrUpdateStaff(openId, phone, null);
        return staff;
    }

    @Override
    public boolean joinPartner() {
        Staff staff = (Staff) LocalDataUtil.getVar(Constants.STAFF_INFO);
        LambdaUpdateWrapper<Staff> wrapper
                = Wrappers.lambdaUpdate(Staff.class).eq(Staff::getId, staff.getId()).set(Staff::getIsPartner, 1);
        if (!this.update(wrapper)) {
            throw new ServiceException("加入失败");
        }
        return true;
    }

    @Override
    public StaffVO getH5StaffInfo() {
        //获取缓存信息
        Staff staff = (Staff) LocalDataUtil.getVar(Constants.STAFF_INFO);
        Long id = staff.getId();

        StaffVO staffVO = new StaffVO();
        BeanUtils.copyProperties(staff, staffVO);
        //服务酬劳信息：从抽成表里边提取

        //保证金信息

        //地址信息
        LambdaQueryWrapper<MemberAddress> wrapper = Wrappers.lambdaQuery(MemberAddress.class).eq(MemberAddress::getStaffId, staff.getId());
        List<MemberAddress> memberAddresses = memberAddressMapper.selectList(wrapper);
        List<MemberAddressVO> memberAddressVOS = BeanUtil.copyToList(memberAddresses, MemberAddressVO.class);
        staffVO.setReceiveOrderAddressList(memberAddressVOS);

        return staffVO;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean saveBaseInfo(StaffAuthenticateBaseInfoRequest request) {
        Staff staff = this.getById(request.getId());
        if (staff == null) {
            throw new ServiceException("未找到伴宠师信息,请检查id是否正确");
        }
        BeanUtil.copyProperties(request, staff, CopyOptions.create(null, true));
        staff.setUpdateTime(LocalDateTime.now());
        this.updateById(staff);
        this.serviceInfoSubmitted(staff.getId(), false,true);
        return true;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean submitBasicCheckResult(BasicCheckResultRequest request) {
        //查询答题人信息
        Staff staff = this.getById(request.getStaffId());
        if (staff == null) {
            throw new ServiceException("未找到员工信息,请检查staffId参数");
        }
        //检查答题次数
        if (staff.getAnswerCount() >= 3) {
            throw new ServiceException("答题超过三次!无法通过");
        }

        if (Boolean.TRUE.equals(request.getPassed())) {
            //答题通过,修改状态为1，通过基础考核
            staff.setAuthenticateStatus(StaffAuthenticateStatusEnum.BASIC_EXAM_PASSED.getKey());
        } else {
            //答题失败，答题次数加一
            Integer answerCount = staff.getAnswerCount();
            staff.setAnswerCount(++answerCount);
        }
        this.updateById(staff);
        return true;
    }

    @Override
    public JSON getBasicQuestion() {
        //读取题目
        InputStream resourceAsStream
                = this.getClass().getClassLoader().getResourceAsStream("basicQuestions.txt");
        String jsonStr = IoUtil.read(resourceAsStream, Charset.forName("UTF-8"));
        JSON result = JSON.parseArray(jsonStr);
        return result;
    }

    @Override
    public JSON getTrainQuestion() {
        InputStream resourceAsStream
                = this.getClass().getClassLoader().getResourceAsStream("trainQuestions.txt");
        String jsonStr = IoUtil.read(resourceAsStream, Charset.forName("UTF-8"));
        JSON result = JSON.parseArray(jsonStr);
        return result;
    }

    @Override
    public boolean submitTrainCheckAnswer(TrainCheckAnswerRequest request) {
        Long staffId = request.getStaffId();
        StaffAnswerRecord record
                = StaffAnswerRecord
                .builder()
                .staffId(staffId)
                .answer(BeanUtil.copyToList(request.getAnswerList(), TrainCheckAnswer.class))
                //审核中
                .status(1)
                .build();
        record.setCreateTime(LocalDateTime.now());
        //如果有审核中的答题记录，禁止提交
        LambdaQueryWrapper<StaffAnswerRecord> recordLambdaQueryWrapper =
                Wrappers.lambdaQuery(StaffAnswerRecord.class)
                        .eq(StaffAnswerRecord::getStaffId, request.getStaffId())
                        .in(StaffAnswerRecord::getStatus, 1, 0);
        if (staffAnswerRecordService.count(recordLambdaQueryWrapper) > 0) {
            throw new ServiceException("答题审核中,请勿重复提交!");
        }
        if (!staffAnswerRecordService.save(record)) {
            throw new ServiceException("保存失败!");
        }
        return true;
    }

    @Override
    public StaffAnswerRecordVO getTrainAnswerRecord(Long staffId) {
        LambdaQueryWrapper<StaffAnswerRecord> wrapper
                = Wrappers
                .lambdaQuery(StaffAnswerRecord.class)
                .eq(StaffAnswerRecord::getStaffId, staffId)
                .orderByDesc(StaffAnswerRecord::getCreateTime)
                .last("limit 1");
        StaffAnswerRecord record = staffAnswerRecordService.getOne(wrapper);
        if (record == null) {
            return null;
        }
        StaffAnswerRecordVO recordVO = BeanUtil.copyProperties(record, StaffAnswerRecordVO.class);
        return recordVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Retryable(value = {RetryException.class}, // 需要重试的异常类型
            maxAttempts = 5,    //最大重试次数为 5
            backoff = @Backoff(delay = 1000, multiplier = 1.5, maxDelay = 10000))
    public synchronized boolean updateStaffBondMoney(Long staffId, BigDecimal money, Integer type) {
        Staff staff = this.getById(staffId);
        if (staff != null) {
            if (money != null && money.compareTo(new BigDecimal(0)) >= 0) {
                if (staff.getBondAmount() != null) {
                    if (1 == type) {//缴纳保证金
                        staff.setBondAmount(money.add(staff.getBondAmount()));
                    } else {//扣减保证金
                        BigDecimal amount = staff.getBondAmount().subtract(money);
                        //如果保证金额度扣除后<=0
                        if (amount.compareTo(new BigDecimal(0)) <= 0) {
                            amount = new BigDecimal(0);
                        }
                        staff.setBondAmount(amount);
                    }
                } else {
                    if (1 == type) {//缴纳保证金
                        staff.setBondAmount(money);
                    }
                }
                Staff updateStaff = new Staff();
                updateStaff.setId(staff.getId());
                updateStaff.setLockVersion(staff.getLockVersion());
                updateStaff.setBondAmount(staff.getBondAmount());
                //如果保证金余额>0 则保证金缴纳状态为已缴纳
                if (staff.getBondAmount().compareTo(new BigDecimal(0)) > 0) {
                    updateStaff.setBondStatus(StaffBondStatus.PAID.getType());
                } else {
                    updateStaff.setBondStatus(StaffBondStatus.UN_PAY.getType());
                }
                boolean result = this.updateById(updateStaff);
                if (!result) {
                    throw new RetryException("更新保证金失败！");
                }
                return result;
            } else {
                log.error("缴纳或扣除的保证金余额{}非正值", money);
            }
        } else {
            log.error("该员工{}不存在!", staffId);
        }
        return false;
    }

    @Override
    public boolean completeServiceInfo(StaffServiceInfoRequest request) {

        //员工信息
        Staff staff = this.getById(request.getId());
        if (staff == null) {
            throw new ServiceException("查询员工信息失败,请检查staffId");
        }

        BeanUtil.copyProperties(request, staff, CopyOptions.create(null, true));

        return this.updateById(staff);

    }

    @Override
    public boolean changeReceiveOrderStatus(StaffChangeReceiveOrderStatusRequest request) {
        //构建更新条件
        LambdaUpdateWrapper<MemberAddress> wrapper = Wrappers.lambdaUpdate(MemberAddress.class)
                .eq(MemberAddress::getStaffId, request.getStaffId())
                .eq(MemberAddress::getId, request.getAddressId())
                .set(MemberAddress::getReceiveOrderStatus, request.getReceiveOrderStatus());
        int count = memberAddressMapper.update(null, wrapper);
        return count >= 1;
    }

    @Override
    public boolean star(StaffStarRequest request) {
        Staff staff = this.getById(request.getStaffId());
        if (staff.getStar() == 0 && request.getStarType() == 0) {
            return true;
        }
        if (request.getStarType() == 0) {
            staff.setStar(staff.getStar() - 1);
        } else {
            staff.setStar(staff.getStar() + 1);
        }
        LambdaUpdateWrapper<Staff> wrapper
                = Wrappers
                .lambdaUpdate(Staff.class)
                .eq(Staff::getId, request.getStaffId())
                .set(Staff::getStar, staff.getStar());
        this.update(wrapper);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void serviceInfoSubmitted(Long staffId, boolean validBaseInfo, boolean validAddressInfo) {
        if (staffId == null) {
            log.error("员工id不能为空");
            return;
        }
        Staff staff = this.getById(staffId);
        if (staff == null) {
            log.error("员工id不能为空,staffId:"+staffId);
            return;
        }
        if (validBaseInfo) {
            //基本信息校验
            if (staff.getServePetType() == null || staff.getServePetType().size() <= 0) {
                log.info("基本信息未填写,不能接单");
                return;
            }

        }
        if (validAddressInfo) {
            //地址信息校验
            LambdaQueryWrapper<MemberAddress> wrapper
                    = Wrappers.lambdaQuery(MemberAddress.class).eq(MemberAddress::getStaffId, staffId);
            Integer count = memberAddressMapper.selectCount(wrapper);
            if (count <=0 ) {
                log.info("地址信息未填写,不能接单");
                return;
            }

        }
        LambdaUpdateWrapper<Staff> wrapper
                = Wrappers.lambdaUpdate(Staff.class).eq(Staff::getId, staffId).set(Staff::getServiceInfoCommitted, 1);
        this.update(wrapper);

    }


    //创建登录日志
    private void insert(Long staffId) {
        Staff staff = staffMapper.selectById(staffId);
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        MemberLogininfor staffLoginInfor = new MemberLogininfor();
        staffLoginInfor.setMemberId(staffId);
        staffLoginInfor.setPhone(staff.getPhoneHidden());
        staffLoginInfor.setOs(userAgent.getOperatingSystem().getName());
        staffLoginInfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
        staffLoginInfor.setBrowser(userAgent.getBrowser().getName());
        staffLoginInfor.setLoginLocation(AddressUtils.getRealAddressByIP(staffLoginInfor.getIpaddr()));
        staffLoginInfor.setLoginTime(LocalDateTime.now());
        staffLoginInfor.setType(1);
        memberLogininforMapper.insert(staffLoginInfor);
    }

    public static String[] parseAddress(String address) {
        // 定义一个正则表达式，匹配省、市、区
        String regex = "([\\u4E00-\\u9FA5]+(省|自治区|直辖市))?\\s*([\\u4E00-\\u9FA5]+(市|地区|自治州))\\s*([\\u4E00-\\u9FA5]+(区|县))";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(address);

        if (matcher.find()) {
            String province = matcher.group(1) != null ? matcher.group(1).trim() : matcher.group(3).trim(); // 省（若没有则用市替代）
            String city = matcher.group(3) != null ? matcher.group(3).trim() : province; // 市（存在则取市名，否则取省名）
            String district = matcher.group(5) != null ? matcher.group(5).trim() : ""; // 区（可选）

            return new String[]{province, city, district}; // 返回省、市、区
        }

        return null ;// 未能解析
    }

}
