package com.fs.hisStore.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.exception.ServiceException;
import com.fs.common.exception.base.BaseException;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.his.param.FsStoreAuditParam;
import com.fs.his.utils.ConfigUtil;
import com.fs.his.utils.StoreMD5PasswordEncoder;
import com.fs.hisStore.domain.FsStoreProductScrm;
import com.fs.hisStore.domain.FsStoreScrm;
import com.fs.hisStore.dto.FsStoreProductScrmInfoDTO;
import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
import com.fs.hisStore.mapper.FsStoreScrmMapper;
import com.fs.hisStore.param.FsStoreScrmInfoParam;
import com.fs.hisStore.service.IFsStoreScrmService;
import com.fs.hisStore.utils.StoreAuditLogUtil;
import com.fs.hisStore.util.BusinessScopeProductTypeUtil;
import com.fs.hisStore.vo.FsStoreDetailsScrmVo;
import com.fs.hisStore.vo.FsStoreRecommendListVO;
import com.fs.hisStore.vo.FsStoreScrmVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 店铺管理Service业务层处理
 *
 * @author fs
 * @date 2023-06-15
 */
@Service
@Slf4j
public class FsStoreScrmServiceImpl implements IFsStoreScrmService {

    @Autowired
    private FsStoreScrmMapper fsStoreMapper;

    @Autowired
    private StoreAuditLogUtil storeAuditLogUtil;

    @Autowired
    private FsStoreProductScrmMapper fsStoreProduct;

    @Autowired
    private ConfigUtil configUtil;

    private static final String MERCHANT_PREFIX = "YJB";

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;


    /**
     * 查询店铺管理
     *
     * @param storeId 店铺管理主键
     * @return 店铺管理
     */
    @Override
    public FsStoreScrm selectFsStoreByStoreId(Long storeId) {
        return fsStoreMapper.selectFsStoreByStoreId(storeId);
    }

    @Override
    public List<FsStoreScrm> selectFsStoreByStoreIds(String[] storeId) {
        return fsStoreMapper.selectFsStoreByStoreIds(storeId);
    }

    /**
     * 查询店铺管理列表
     *
     * @param fsStore 店铺管理
     * @return 店铺管理
     */
    @Override
    public List<FsStoreScrm> selectFsStoreList(FsStoreScrm fsStore) {
        return fsStoreMapper.selecStorePageList(fsStore);
    }

    /**
     * 新增店铺管理
     *
     * @param fsStore 店铺管理
     * @return 结果
     */
    @Override
    public Long insertFsStore(FsStoreScrm fsStore) {
        //检查商家填写的账号是否重复
        if (fsStore.getAccount() != null) {
            FsStoreScrm fs = fsStoreMapper.selectFsStoreByAccount(fsStore.getAccount());
            if (fs != null) {
                throw new CustomException("店铺账号重复");
            }
        }
        StoreMD5PasswordEncoder storeMD5PasswordEncoder = new StoreMD5PasswordEncoder();
        fsStore.setPassword(storeMD5PasswordEncoder.encode("XyzAbc~12"));
        fsStore.setCreateTime(DateUtils.getNowDate());
        if (fsStore.getBusinessCode() != null && !fsStore.getBusinessCode().trim().isEmpty()) {
            boolean exists = fsStoreMapper.existsByBusinessCode(fsStore.getBusinessCode());
            if (exists) {
                // 检查是否是同一个商家
                String existingMerchantId = fsStoreMapper.findMerchantIdByBusinessCode(fsStore.getBusinessCode());
                if (existingMerchantId != null) {
                    // 同一商家下检查店铺名称是否重复
                    if (fsStoreMapper.existsStoreNameInMerchant(existingMerchantId, fsStore.getStoreName())) {
                        throw new CustomException("该商家下已存在同名店铺");
                    }
                }
            }
        }
        //生成商家id
        String merchantId = generateMerchantId(fsStore.getBusinessCode());
        //生成店铺id
        String sequence = generateStoreSequence();
        fsStore.setMerchantId(merchantId);
        fsStore.setStoreSeq(sequence);
        fsStore.setQualificationUpdateTime(LocalDate.now());
        fsStoreMapper.insertFsStore(fsStore);
        //信息发布
        applicationEventPublisher.publishEvent(fsStore);
        return fsStore.getStoreId();
    }

    /**
     * 生成商家ID：YJB202510180001
     * 格式：前缀 + 年月日 + 4位序列号
     */
    @Transactional
    public String generateMerchantId(String businessCode) {
        // 如果营业执照已存在，返回已有的商家ID
        if (businessCode != null && !businessCode.trim().isEmpty()) {
            String existingMerchantId = fsStoreMapper.findMerchantIdByBusinessCode(businessCode);
            if (existingMerchantId != null) {
                return existingMerchantId;
            }
        }

        // 新营业执照，生成新的商家ID
        String datePart = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String prefix = MERCHANT_PREFIX + datePart;

        // 查询当天已生成的新商家数量（基于营业执照）
        Long todayNewMerchantCount = fsStoreMapper.countNewMerchantsByDate(prefix);
        Long sequence = (todayNewMerchantCount == null) ? 1L : todayNewMerchantCount + 1;

        return prefix + String.format("%04d", sequence);
    }


    /**
     * 生成店铺序号：年月日 + 当天第几家店
     * 格式：202510180001
     */
    @Transactional
    public String generateStoreSequence() {
        String datePart = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

//        // 检查是否是新商家（根据营业执照是否已存在）
//        boolean isNewMerchant = false;
//        if (businessCode != null && !businessCode.trim().isEmpty()) {
//            String existingMerchantId = fsStoreMapper.findMerchantIdByBusinessCode(businessCode);
//            isNewMerchant = (existingMerchantId == null);
//        } else {
//            // 如果没有营业执照，检查商家ID是否已存在
//            Integer existingStoreCount = fsStoreMapper.countStoresByMerchant(merchantId);
//            isNewMerchant = (existingStoreCount == null || existingStoreCount == 0);
//        }
//
//        if (isNewMerchant) {
//            // 新商家，店铺序列从1开始
//            return datePart + "0001";
//        } else {
//            // 现有商家，获取当前商家的店铺数量+1
//            Integer storeCount = fsStoreMapper.countStoresByMerchant(merchantId);
//            Long sequence = (storeCount == null) ? 1L : storeCount + 1L;
//            return datePart + String.format("%04d", sequence);
//        }

        // 获取当天已生成的店铺数量
        Long todayStoreCount = fsStoreMapper.countByStoreSeqPrefix(datePart);

        // 序号从1开始，每天重置
        Long sequence = (todayStoreCount == null) ? 1L : todayStoreCount + 1L;

        return datePart + String.format("%04d", sequence);
    }

    /**
     * 修改店铺管理
     *
     * @param fsStore 店铺管理
     * @return 结果
     */
    @Override
    public int updateFsStore(FsStoreScrm fsStore) {
        fsStore.setUpdateTime(DateUtils.getNowDate());
        storeAuditLogUtil.addOperLog(fsStore.getStoreId());
        FsStoreScrm oldFsStore = fsStoreMapper.selectFsStoreByStoreId(fsStore.getStoreId());
        Boolean isAudit = configUtil.generateConfigByKey("medicalMall.func.switch").getBoolean("isAudit");
        try {
            if (isAudit != null && isAudit) {
                //驳回修改时，将isAudit设置为0
                if (fsStore.getIsAudit() != null && (1 == fsStore.getIsAudit() || -1 == fsStore.getIsAudit())) {
                    Map<String, Object> diff = getDiff(oldFsStore, fsStore);
                    Set<String> diff_columns = diff.keySet();
                    JSONArray storeColumns = configUtil.generateConfigByKey("medicalMall.func.switch").getJSONArray("storeColumns");
                    if (StringUtils.isNotEmpty(storeColumns)) {
                        //判断diff_columns是否在storeColumns中，不是则将isAudit设置为0
                        for (String column : diff_columns) {
                            if (!storeColumns.contains(column)) {
                                fsStore.setIsAudit(0);
                                break;
                            }
                        }
                    } else {
                        fsStore.setIsAudit(0);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            log.error("获取diff出错", e);
        }
        fsStore.setQualificationUpdateTime(LocalDate.now());
        int updateRowNum = fsStoreMapper.updateFsStore(fsStore);
        //信息发布
        if(updateRowNum > 0){
            applicationEventPublisher.publishEvent(fsStore);
        }
        return updateRowNum;
    }

    @Override
    public List<String> queryValidStoreQualifications() {
        return fsStoreMapper.queryValidStoreQualifications();
    }

    public static Map<String, Object> getDiff(Object obj1, Object obj2) throws IllegalAccessException {
        Map<String, Object> diff = new HashMap<>();
        if (obj1 == null || obj2 == null || !obj1.getClass().equals(obj2.getClass())) {
            return diff;
        }

        Field[] fields = obj1.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object value1 = field.get(obj1);
            Object value2 = field.get(obj2);
            // BigDecimal类型特殊处理
            if (value1 instanceof BigDecimal && value2 instanceof BigDecimal) {
                BigDecimal bd1 = (BigDecimal) value1;
                BigDecimal bd2 = (BigDecimal) value2;
                // 使用compareTo方法比较，避免精度问题
                if (bd1.compareTo(bd2) != 0) {
                    diff.put(field.getName(), new Object[]{value1, value2});
                }
            }
            // 其他类型使用默认比较
            else if (!Objects.equals(value1, value2)) {
                diff.put(field.getName(), new Object[]{value1, value2});
            }
        }
        return diff;
    }

    /**
     * 批量删除店铺管理
     *
     * @param storeIds 需要删除的店铺管理主键
     * @return 结果
     */
    @Override
    public R deleteFsStoreByStoreIds(Long[] storeIds) {
        //获取数据
        List<FsStoreProductScrmInfoDTO> storeInfos = fsStoreMapper.getStoreInfo(storeIds);
        storeAuditLogUtil.addBatchAuditArray(storeIds, null, null);
        StringBuilder sb = new StringBuilder();
        sb.append("删除成功");
        if(fsStoreMapper.deleteFsStoreByStoreIds(storeIds) > 0){
            storeInfos.forEach(storeInfo -> {
                sb.append("删除店铺ID：").append(storeInfo.getStoreId()).append("-")
                        .append("删除店铺：").append(storeInfo.getStoreName()).append("/");

            });
        }
        return  R.ok(sb.toString());
    }

    /**
     * 删除店铺管理信息
     *
     * @param storeId 店铺管理主键
     * @return 结果
     */
    @Override
    public int deleteFsStoreByStoreId(Long storeId) {
        return fsStoreMapper.deleteFsStoreByStoreId(storeId);
    }

    @Override
    @Transactional
    public int updateFsStoreAudit(FsStoreAuditParam fsStore) {

        FsStoreScrm fsStoreScrm = fsStoreMapper.selectFsStoreByStoreId(fsStore.getStoreId());
        if (fsStoreScrm == null) {
            throw new ServiceException("操作失败，审核店铺数据不存在！");
        }
        FsStoreScrm updateStore = new FsStoreScrm();
        updateStore.setStoreId(fsStore.getStoreId());
        updateStore.setIsAudit(fsStore.getIsAudit());
        
        // 审核通过时，根据经营范围自动设置可选商品类型
        if (fsStore.getIsAudit() != null && fsStore.getIsAudit() == 1) {
            if (StringUtils.isNotEmpty(fsStoreScrm.getBusinessScope())) {
                String selectableProductTypes = BusinessScopeProductTypeUtil.determineProductTypes(fsStoreScrm.getBusinessScope());
                updateStore.setSelectableProductTypes(selectableProductTypes);
                log.info("店铺[{}]审核通过，根据经营范围[{}]自动设置可选商品类型：{}", 
                        fsStore.getStoreId(), fsStoreScrm.getBusinessScope(), selectableProductTypes);
            }
        }
        //审核过后更新
        if(fsStore.getIsAudit() != null && fsStore.getIsAudit() == 1){
            updateStore.setQualificationUpdateTime(LocalDate.now());
        }
        updateStore.setStatus(1);
        fsStoreMapper.updateFsStore(updateStore);
        //更新日志
        storeAuditLogUtil.addAudit(fsStore.getStoreId(), fsStore.getReason(), fsStore.getAttachImage());
        return 1;
    }

    @Override
    public int updateFsStoreLogo(FsStoreScrm fsStore) {
        return fsStoreMapper.updateFsStore(fsStore);
    }

    @Override
    public int updateEditData(FsStoreScrm fsStore) {
        return fsStoreMapper.updateFsStore(fsStore);
    }

    @Override
    public List<FsStoreScrm> selectFsStoreListByDoctorId(Long doctorId) {
        return fsStoreMapper.selectFsStoreListByDoctorId(doctorId);
    }

    @Override
    public int refreshFsStore(Long storeId) {
        FsStoreScrm fsStoreScrm = new FsStoreScrm();
        fsStoreScrm.setStoreId(storeId);
        StoreMD5PasswordEncoder storeMD5PasswordEncoder = new StoreMD5PasswordEncoder();
        fsStoreScrm.setPassword(storeMD5PasswordEncoder.encode("XyzAbc~12"));
        fsStoreScrm.setUpdateTime(DateUtils.getNowDate());
        storeAuditLogUtil.addOperLog(storeId);
        return fsStoreMapper.updateFsStore(fsStoreScrm);
    }

    @Override
    public List<FsStoreScrm> selectOverList() {
        return fsStoreMapper.selectOverList();
    }

    @Override
    public int batchUpdateStatusByIds(List<Long> ids, Integer status) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        return fsStoreMapper.batchUpdateStatusByIds(ids, status);
    }

    @Override
    public List<FsStoreRecommendListVO> storeRecommendList() {
        FsStoreScrm fsStoreScrm = new FsStoreScrm();
        fsStoreScrm.setStatus(1);//启用
        fsStoreScrm.setIsAudit(1);//审核通过
        //List<FsStoreScrm>  storeList =  fsStoreMapper.selectFsStoreList( fsStoreScrm);
//        List<FsStoreScrm>  storeList =  fsStoreMapper.selectFsStoreList(fsStoreScrm);
        List<FsStoreScrm> storeList = fsStoreMapper.selectFsStoreListByProduct(fsStoreScrm); //查询有商品的列表
        return storeList.stream().map(store -> {
            FsStoreProductScrm fsStoreProductScrm = new FsStoreProductScrm();
            fsStoreProductScrm.setStoreId(store.getStoreId());
            fsStoreProductScrm.setIsAudit("1");//审核通过
            fsStoreProductScrm.setIsBest(1);//推荐
            fsStoreProductScrm.setIsGood(1);//上架
            fsStoreProductScrm.setIsDel(0);
            List<FsStoreProductScrm> fsStoreProductScrms = fsStoreProduct.selectFsStoreProductList(fsStoreProductScrm);
            return FsStoreRecommendListVO.builder().store(store).recommendProductList(fsStoreProductScrms).build();
        }).collect(Collectors.toList());
    }

    @Override
    public List<FsStoreScrmVO> selectAllStore() {
        return fsStoreMapper.selectFsAllStoreList();
    }

    @Override
    public List<Map<String, String>> getStoreColumns() {
        List<Map<String, String>> list = fsStoreMapper.getStoreColumns();
        List<Map<String, String>> result = new ArrayList<>();

        for (Map<String, String> column : list) {
            Map<String, String> camelCaseColumn = new HashMap<>();
            String columnName = column.get("colName");
            String camelCaseName = StringUtils.toCamelCase(columnName);
            camelCaseColumn.put("colName", camelCaseName);
            camelCaseColumn.put("colComment", column.get("colComment"));
            result.add(camelCaseColumn);
        }

        return result;
    }

    @Override
    public List<FsStoreScrm> selectFsStoreListOption(FsStoreScrm fsStore) {
        return fsStoreMapper.selectFsStoreListOption(fsStore);
    }

    @Override
    public List<String> getStoreAgreementExpiryTips() {
        return fsStoreMapper.queryValidStoreAgreementExpiryTips();
    }

    @Override
    public FsStoreDetailsScrmVo getStoreInfoByStoreId(Long storeId) {
        return fsStoreMapper.selectStoreInfoByStoreId(storeId);
    }

    /**
     * 修改店铺管理
     *
     * @param fsStore 店铺管理
     * @return 结果
     */
    @Override
    public int updateStoreInfo(FsStoreScrmInfoParam fsStore) {
        storeAuditLogUtil.addOperLog(fsStore.getStoreId());
        FsStoreScrm oldFsStore = fsStoreMapper.selectFsStoreByStoreId(fsStore.getStoreId());
        fsStore.setIsAudit(oldFsStore.getIsAudit());
        // 获取审核开关配置
        Boolean isAuditEnabled = configUtil.generateConfigByKey("medicalMall.func.switch").getBoolean("isAudit");
        try {
            // 仅当开启审核功能时才进行判断
            if (Boolean.TRUE.equals(isAuditEnabled) && (oldFsStore.getIsAudit() == 1 || oldFsStore.getIsAudit() == -1)) {
//                if (getFullDiff(oldFsStore, fsStore)) {
//                    fsStore.setIsAudit(0);
//                }
                fsStore.setIsAudit(0);
            }
        } catch (Exception e) {
            log.error("处理审核状态出错", e);
        }

        FsStoreScrm updateStore = new FsStoreScrm();
        BeanUtils.copyProperties(fsStore, updateStore);
        updateStore.setUpdateTime(DateUtils.getNowDate());
        int updateRowNum = fsStoreMapper.updateFsStore(updateStore);
        //信息发布
        applicationEventPublisher.publishEvent(fsStore);
        return updateRowNum;
    }

    @Override
    public void merchantQualificationExpiryCheck() {
        log.info("定时任务店铺资质过期更新状态--------------------------start{}");
        //获取资质过期商铺
        List<Long> storeIds = fsStoreMapper.getStoreQualificationExpiredInfo();
        if (!storeIds.isEmpty()) {
            //更新商铺状态】
            fsStoreMapper.batchUpdateStoreStatusById(storeIds);
        }
        log.info("定时任务店铺资质过期更新状态--------------------------end{}");
    }

    @Override
    public List<String> queryValidStoreLastInfo(Long storeId) {
        return fsStoreMapper.queryValidStoreLastInfo(storeId);
    }

    @Override
    public R qualificationReminder(Long storeId) {
        FsStoreScrm storeScrm = fsStoreMapper.qualificationReminder(storeId);
        if (storeScrm != null) {
            if(storeScrm.getStatus().equals(1) && storeScrm.getRemainDays() < 0){
                //更新店铺状态
                FsStoreScrm fsStoreScrm =new FsStoreScrm();
                fsStoreScrm.setStoreId(storeId);
                fsStoreScrm.setStatus(0);
                fsStoreMapper.updateFsStore(fsStoreScrm);
            }
        }
        return R.ok().put("data",storeScrm);
    }

    /**
     * 获取两个对象的所有差异字段（基于旧对象的所有字段，以新对象字段值为准进行对比）
     * 只要新旧值不同就视为差异
     */
    private Boolean getFullDiff(FsStoreScrm oldObj, FsStoreScrmInfoParam newObj) throws IllegalAccessException {
        Field[] newFields = newObj.getClass().getDeclaredFields();
        for (Field oldField : newFields) {
            oldField.setAccessible(true);
            String fieldName = oldField.getName();
//            if (isExcludedField(fieldName)) {
//                continue;
//            }
            Object newValue = oldField.get(newObj);
            Object oldValue = getFieldValue(oldObj, fieldName);
            if (!Objects.equals(oldValue, newValue)) {
                return true;
            }
        }
        return false;
    }

    private Object getFieldValue(FsStoreScrm obj, String fieldName) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (NoSuchFieldException e) {
            return null;
        } catch (IllegalAccessException e) {
            log.error("获取字段值失败: " + fieldName, e);
            return null;
        }
    }

//    private boolean isExcludedField(String fieldName) {
//        Set<String> excludedFields = new HashSet<>(Arrays.asList(
//                "balance", "createTime", "storeId","",""
//        ));
//        return excludedFields.contains(fieldName);
//    }
}

