package shop.alien.store.controller;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartRequest;
import shop.alien.entity.result.R;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.StoreInfoDto;
import shop.alien.entity.store.vo.*;
import shop.alien.entity.storePlatform.StoreLicenseHistory;
import shop.alien.mapper.*;
import shop.alien.mapper.storePlantform.StoreLicenseHistoryMapper;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.service.*;
import shop.alien.entity.store.StoreCuisine;
import shop.alien.entity.store.StorePrice;
import shop.alien.entity.store.UserLoginInfo;
import shop.alien.store.util.StoreClockInIdentityHelper;
import shop.alien.util.common.TokenInfo;
import shop.alien.util.type.LifeFansIdentityQuery;
import shop.alien.util.type.TypeUtil;
import springfox.documentation.annotations.ApiIgnore;

import java.io.IOException;
import java.util.*;

/**
 * 二期-门店信息Controller
 *
 * @author ssk
 * @since 2024-12-05
 */
@Slf4j
@Api(tags = {"二期-门店信息"})
@ApiSort(1)
@CrossOrigin
@RestController
@RequestMapping("/store/info")
@RequiredArgsConstructor
public class StoreInfoController {

    private final StoreInfoService storeInfoService;

    private final StoreUserService storeUserService;

    private final StoreQualificationService storeQualificationService;

    private final TagsMainMapper tagsMainMapper;

    private final WebAuditMapper webAuditMapper;

    private final BaseRedisService baseRedisService;

    private final StoreCommentSummaryInterestMapper storeCommentSummaryInterestMapper;

    /** 商户证照历史记录数据访问对象 */
    private final StoreLicenseHistoryMapper licenseHistoryMapper;

    private final StoreImgMapper storeImgMapper;

    private final StoreCommentMapper storeCommentMapper;
    private final StoreClockInMapper storeClockInMapper;
    private final LifeUserMapper lifeUserMapper;
    private final StoreInfoMapper storeInfoMapper;
    private final LifeBlacklistMapper lifeBlacklistMapper;
    private final StoreUserMapper storeUserMapper;
    private final LifeFansMapper lifeFansMapper;
    private final TypeUtil typeUtil;

    private final StoreClockInIdentityHelper clockInIdentityHelper;

    private final StoreCuisineService storeCuisineService;
    private final StorePriceService storePriceService;
    private final StoreStaffConfigService storeStaffConfigService;
    private final PerformanceListService performanceListService;
    private final SportsEquipmentFacilityService sportsEquipmentFacilityService;

    @ApiOperation("获取所有门店")
    @ApiOperationSupport(order = 1)
    @GetMapping("/getAll")
    public R<List<StoreInfo>> getAll() {
        log.info("StoreInfoController.getAll");
        return R.data(storeInfoService.list());
    }

    @ApiOperation("根据id获取门店")
    @ApiOperationSupport(order = 2)
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "Long", paramType = "query", required = true)})
    @GetMapping("/getOne")
    public R<StoreInfo> getOne(Integer id) {
        log.info("StoreInfoController.getOne?id={}", id);
        return R.data(storeInfoService.getById(id));
    }

    @ApiOperation("门店装修-编辑门店信息")
    @ApiOperationSupport(order = 3)
    @PostMapping("/saveOrUpdate")
    public R<StoreInfo> saveOrUpdate(@RequestBody StoreInfoDto storeInfo) {
        log.info("StoreInfoController.saveOrUpdate?storeInfo={}", storeInfo);
        try {
            int num = storeInfoService.saveOrUpdateStoreInfo(storeInfo);
            if (num > 0) {
                return R.success("成功");
            }
            return R.fail("失败");
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    @ApiOperation("web端新增门店")
    @ApiOperationSupport(order = 3)
    @PostMapping("/saveStoreInfo")
    public R saveStoreInfo(@RequestBody StoreInfoDto storeInfoDto) throws Exception {
        log.info("StoreInfoController.saveStoreInfo?storeInfoDto={}", storeInfoDto);
        StoreInfoVo storeInfoVo = storeInfoService.saveStoreInfo(storeInfoDto);
        if (storeInfoVo != null) {
            return R.data(storeInfoVo);
        }
        return R.fail("失败");
    }


    @ApiOperation("新增门店草稿")
    @ApiOperationSupport(order = 3)
    @PostMapping("/saveStoreInfoDraft")
    public R<Boolean> saveStoreInfoDraft(@RequestBody StoreInfoDraft storeInfoDraft) {
        log.info("StoreInfoController.saveStoreInfoDraft?storeInfoDraft={}", storeInfoDraft);
        int num = storeInfoService.saveStoreInfoDraft(storeInfoDraft);
        if (num > 0) {
            return R.data(true);
        }
        return R.fail("失败");
    }

    @ApiOperation("查询门店草稿")
    @ApiOperationSupport(order = 3)
    @GetMapping("/selectDraftByUserId")
    public R<StoreInfoDraft> selectDraftByUserId(int storeUserId) throws Exception {
        log.info("StoreInfoController.saveStoreInfoDraft?storeUserId={}", storeUserId);
        return R.data(storeInfoService.selectDraftByUserId(storeUserId));
    }


    @ApiOperation("web端修改门店")
    @ApiOperationSupport(order = 3)
    @PostMapping("/editStoreInfo")
    public R editStoreInfo(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.editStoreInfo?storeInfoDto={}", storeInfoDto);
        StoreInfoVo storeInfoVo = storeInfoService.editStoreInfo(storeInfoDto);
        if (storeInfoVo != null) {
            return R.data(storeInfoVo);
        }
        return R.fail("失败");
    }

    @ApiOperation("web修改门店抽成")
    @ApiOperationSupport(order = 3)
    @PostMapping("/updateStoreCommissionRate")
    public R updateStoreCommissionRate(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.updateStoreCommissionRate?storeInfoDto={}", storeInfoDto);
        if (storeInfoService.editStoreCommissionRate(storeInfoDto) > 0) {
            return R.data("成功");
        }
        return R.fail("失败");
    }

    @ApiOperation("web端删除门店")
    @ApiOperationSupport(order = 3)
    @PostMapping("/deleteStoreInfo")
    public R deleteStoreInfo(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.deleteStoreInfo?storeInfoDto={}", storeInfoDto);
        String s;
        try {
            s = storeInfoService.deleteStoreInfo(storeInfoDto);
        } catch (Exception e) {
            return R.fail("失败");
        }
        if ("成功".equals(s)) {
            return R.success(s);
        } else {
            return R.fail(s);
        }
    }

    @ApiOperation("web端重置商户及管理账户密码")
    @ApiOperationSupport(order = 3)
    @PostMapping("/restPassword")
    public R restPassword(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.restPassword?storeInfoDto={}", storeInfoDto);
        try {
            storeInfoService.restPassword(storeInfoDto);
        } catch (Exception e) {
            return R.fail("失败");
        }
        return R.success("成功");
    }

    @ApiOperation(value = "删除门店")
    @ApiOperationSupport(order = 4)
    @PostMapping("/delete")
    public R<String> delete(@RequestBody List<Integer> ids) {
        log.info("StoreInfoController.delete?ids={}", ids);
        if (storeInfoService.removeByIds(ids)) {
            return R.success("删除成功");
        }
        return R.fail("删除失败");
    }

    @ApiOperation(value = "门店详细信息")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "Long", paramType = "query", required = true)})
    @GetMapping("/getDetail")
    public R<StoreMainInfoVo> getDetail(Integer id) {
        log.info("StoreInfoController.getDetail?id={}", id);
        return R.data(storeInfoService.getDetail(id));
    }

    @ApiOperation(value = "门店详细信息（通过商家手机号）")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "商家手机号", dataType = "String", paramType = "query", required = true)})
    @GetMapping("/getDetailByPhone")
    public R<StoreMainInfoVo> getDetailByPhone(@RequestParam("phone") String phone) {
        log.info("StoreInfoController.getDetailByPhone?phone={}", phone);
        try {
            // 根据手机号查询 store_user
            LambdaQueryWrapper<StoreUser> userWrapper = new LambdaQueryWrapper<>();
            userWrapper.eq(StoreUser::getPhone, phone)
                      .eq(StoreUser::getDeleteFlag, 0);
            StoreUser storeUser = storeUserMapper.selectOne(userWrapper);
            
            if (storeUser == null) {
                log.warn("未找到手机号对应的商家用户: phone={}", phone);
                return R.fail("未找到该手机号对应的商家");
            }
            
            // 如果 store_id 不为空，则使用该 store_id 查询门店详细信息
            if (storeUser.getStoreId() != null && storeUser.getStoreId() > 0) {
                // 先查询门店信息，检查审核状态和删除标记
                StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());
                
                if (storeInfo == null) {
                    log.warn("门店不存在: storeId={}, phone={}", storeUser.getStoreId(), phone);
                    return R.fail("门店不存在");
                }
                
                // 排除被删除的门店
                if (storeInfo.getDeleteFlag() != null && storeInfo.getDeleteFlag() != 0) {
                    log.warn("门店已被删除: storeId={}, phone={}, deleteFlag={}", 
                            storeUser.getStoreId(), phone, storeInfo.getDeleteFlag());
                    return R.fail("门店已被删除");
                }
                
                // 排除审核状态为2（审核失败）的门店
                if (storeInfo.getStoreApplicationStatus() != null && storeInfo.getStoreApplicationStatus() == 2) {
                    log.warn("门店审核失败: storeId={}, phone={}, storeApplicationStatus={}", 
                            storeUser.getStoreId(), phone, storeInfo.getStoreApplicationStatus());
                    return R.fail("门店审核失败");
                }
                
                return R.data(storeInfoService.getDetail(storeUser.getStoreId()));
            } else {
                log.warn("商家用户的 store_id 为空: phone={}, userId={}", phone, storeUser.getId());
                return R.fail("该商家未关联门店");
            }
        } catch (Exception e) {
            log.error("根据手机号查询门店详细信息失败: phone={}", phone, e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "门店信息-修改后展示")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "Long", paramType = "query", required = true)})
    @GetMapping("/getStoreInfo")
    public R<StoreMainInfoVo> getStoreInfo(Integer id) {
        log.info("StoreInfoController.getStoreInfo?id={}", id);
        return R.data(storeInfoService.getStoreInfo(id));
    }

    /**
     * web-分页查询店铺信息
     *
     * @param pageNum      页码
     * @param pageSize     页容
     * @param storeName    门店名称
     * @param storeContact 联系人
     * @param storePhone   门店电话
     * @param storeType    门店类型
     * @return IPage<StoreInfoVo>
     */
    @ApiOperation("web-分页查询店铺信息")
    @ApiOperationSupport(order = 7)
    @ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true), @ApiImplicitParam(name = "storeName", value = "门店名称", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storeContact", value = "门店联系人", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storePhone", value = "门店电话", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storeType", value = "门店类型", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "expiredState", value = "过期状态", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storeApplicationStatus", value = "门店审核状态", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "jingdu", value = "jingdu", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "weidu", value = "weidu", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "renewContractStatus", value = "门店续签合同状态", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "foodLicenceStatus", value = "门店经营许可证状态", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "foodLicenceWhetherExpiredStatus", value = "门店经营许可证是否过期状态", dataType = "String", paramType = "query")})
    @GetMapping("/getStorePage")
    public R<IPage<StoreInfoVo>> getStoresPage(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize, @RequestParam(required = false) String storeName, @RequestParam(required = false) String storeContact, @RequestParam(required = false) String id, @RequestParam(required = false) String storePhone, @RequestParam(required = false) String storeType, @RequestParam(required = false) String expiredState, @RequestParam(required = false) String storeApplicationStatus, @RequestParam(required = false) String businessSection, @RequestParam(required = false) String storeStatus, @RequestParam(required = false) String jingdu, @RequestParam(required = false) String weidu, @RequestParam(required = false) String renewContractStatus, @RequestParam(required = false) String foodLicenceStatus, @RequestParam(required = false) String foodLicenceWhetherExpiredStatus) {
        log.info("StoreInfoController.getStoresPage?pageNum={},pageSize={},storeName={},storeContact={},id={},storePhone={},storeType={},expiredState={},storeApplicationStatus={},storeStatus={},businessSection={},jingdu={},weidu={},renewContractStatus={},foodLicenceStatus={},foodLicenceWhetherExpiredStatus={}", pageNum, pageSize, storeName, storeContact, id, storePhone, storeType, expiredState, storeApplicationStatus, storeStatus, businessSection, jingdu, weidu, renewContractStatus, foodLicenceStatus, foodLicenceWhetherExpiredStatus);
        return R.data(storeInfoService.getStorePage(pageNum, pageSize, storeName, storeContact, id, storePhone, storeType, expiredState, storeApplicationStatus, storeStatus, businessSection, jingdu, weidu, renewContractStatus, foodLicenceStatus, foodLicenceWhetherExpiredStatus));
    }

    /**
     * 新web-分页查询店铺信息
     *
     * @param pageNum      页码
     * @param pageSize     页容
     * @param storeName    门店名称
     * @param storeContact 联系人
     * @param storePhone   门店电话
     * @param storeType    门店类型
     * @return IPage<StoreInfoVo>
     */
    @ApiOperation("新中台web-分页查询店铺信息")
    @ApiOperationSupport(order = 20)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "storeName", value = "门店名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeContact", value = "门店联系人", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storePhone", value = "门店电话", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeType", value = "门店类型", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "expiredState", value = "过期状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeApplicationStatus", value = "门店审核状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "jingdu", value = "jingdu", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "weidu", value = "weidu", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "renewContractStatus", value = "门店续签合同状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "foodLicenceStatus", value = "门店经营许可证状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "foodLicenceWhetherExpiredStatus", value = "门店经营许可证是否过期状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "startApplyTime", value = "开始时间", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endApplyTime", value = "结束时间", dataType = "String", paramType = "query")
    })
    @GetMapping("/getNewStorePage")
    public R<IPage<StoreInfoVo>> getNewStorePage(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String storeName,
            @RequestParam(required = false) String storeContact,
            @RequestParam(required = false) String id,
            @RequestParam(required = false) String storePhone,
            @RequestParam(required = false) String storeType,
            @RequestParam(required = false) String expiredState,
            @RequestParam(required = false) String storeApplicationStatus,
            @RequestParam(required = false) String businessSection,
            @RequestParam(required = false) String storeStatus,
            @RequestParam(required = false) String jingdu,
            @RequestParam(required = false) String weidu,
            @RequestParam(required = false) String renewContractStatus,
            @RequestParam(required = false) String foodLicenceStatus,
            @RequestParam(required = false) String foodLicenceWhetherExpiredStatus,
            @RequestParam(required = false) String startApplyTime,
            @RequestParam(required = false) String endApplyTime)
    {
        log.info("StoreInfoController.getStoresPage?pageNum={}," +
                        "pageSize={},storeName={},storeContact={}," +
                        "id={},storePhone={},storeType={},expiredState={}," +
                        "storeApplicationStatus={},storeStatus={}," +
                        "businessSection={},jingdu={},weidu={}," +
                        "renewContractStatus={},foodLicenceStatus={}" +
                        ",foodLicenceWhetherExpiredStatus={},startApplyTime={},endApplyTime={}",
                pageNum, pageSize, storeName, storeContact,
                id, storePhone, storeType, expiredState, storeApplicationStatus,
                storeStatus, businessSection, jingdu, weidu, renewContractStatus,
                foodLicenceStatus, foodLicenceWhetherExpiredStatus, startApplyTime, endApplyTime);
        return R.data(storeInfoService.getNewStorePage(pageNum, pageSize, storeName, storeContact, id, storePhone, storeType, expiredState, storeApplicationStatus, storeStatus, businessSection, jingdu, weidu, renewContractStatus, foodLicenceStatus, foodLicenceWhetherExpiredStatus, startApplyTime, endApplyTime));
    }

    /**
     * web-重置门店密码
     *
     * @param storeId 门店id
     * @return R
     */
    @ApiOperation("web-重置门店密码")
    @ApiOperationSupport(order = 8)
    @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query")})
    @GetMapping("/resetPassword")
    public R<Boolean> resetPassword(@RequestParam("storeId") String storeId) {
        log.info("StoreInfoController.resetPassword?id={}", storeId);
        if (storeInfoService.resetPassword(storeId)) {
            return R.success("密码重置成功");
        }
        return R.fail("密码重置失败");
    }

    /**
     * web-修改门店状态
     *
     * @param storeId        门店id
     * @param businessStatus 营业状态
     * @return R
     */
    @ApiOperation("web-修改门店状态")
    @ApiOperationSupport(order = 9)
    @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query"), @ApiImplicitParam(name = "businessStatus", value = "营业状态(0:正常营业, 1:暂停营业, 2:筹建中, 99:永久关门)", dataType = "int", paramType = "query")})
    @GetMapping("/setStoreState")
    public R<Boolean> setStoreState(@RequestParam("storeId") String storeId, @RequestParam("businessStatus") Integer businessStatus) {
        log.info("StoreInfoController.setStoreState?storeId={},storeState={}", storeId, businessStatus);
        if (storeInfoService.setStoreState(storeId, businessStatus)) {
            return R.success("状态修改成功");
        }
        return R.fail("状态修改失败");
    }

    /**
     * web-新增店铺
     *
     * @param multipartRequest 文件请求
     * @param store            店铺信息
     * @return R
     */
    @ApiOperation("web-新增店铺")
    @ApiOperationSupport(order = 10)
    @PostMapping("/saveStore")
    public R<Boolean> saveStore(MultipartRequest multipartRequest, StoreInfo store) {
        Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
        log.info("StoreInfoController.saveStore?store={}&file={}", store.toString(), fileNameSet);
        if (storeInfoService.saveStore(multipartRequest, store)) {
            return R.success("新增成功");
        }
        return R.fail("新增失败");
    }

    @ApiOperation("web-导出Excel")
    @ApiOperationSupport(order = 11)
    @GetMapping("/export")
    public ResponseEntity<byte[]> exportToExcel() {
        log.info("StoreInfoController.exportToExcel");
        return storeInfoService. exportToExcel();
    }

    @ApiOperation(value = "web端查询经营板块信息")
    @ApiOperationSupport(order = 6)
    @GetMapping("/getBusinessSection")
    public R<List<StoreDictionaryVo>> getBusinessSection() {
        log.info("StoreInfoController.getBusinessSection");
        return R.data(storeInfoService.getBusinessSection());
    }

    @ApiOperation(value = "web端查询经营板块的经营种类信息")
    @ApiOperationSupport(order = 6)
    @GetMapping("/getBusinessSectionTypes")
    public R<List<StoreDictionaryVo>> getBusinessSectionTypes(@RequestParam("parentId") String parentId) {
        log.info("StoreInfoController.getBusinessSectionTypes?parentId={}", parentId);
        return R.data(storeInfoService.getBusinessSectionTypes(parentId));
    }

    @ApiOperation(value = "web端查询未绑定店铺的商家端账号")
    @ApiOperationSupport(order = 6)
    @GetMapping("/getUnboundAccountList")
    public R<List<StoreUserVo>> getUnboundAccountList(@RequestParam(value = "id", required = false) String id) {
        log.info("StoreInfoController.getUnboundAccountList");
        return R.data(storeInfoService.getUnboundAccountList(id));
    }

    @ApiOperation(value = "web端新增经营板块及经营类型")
    @ApiOperationSupport(order = 6)
    @PostMapping("/addBusinessSectionAndTypes")
    public R addBusinessSectionAndTypes(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.addBusinessSectionAndTypes");
        storeInfoService.addBusinessSectionAndTypes(storeInfoDto);
        return R.success("新增成功");
    }

    @ApiOperation(value = "web端获取店铺明细详情")
    @ApiOperationSupport(order = 6)
    @GetMapping("/getStoreDetail")
    public R getStoreDetail(@RequestParam("id") String id, @RequestParam(value = "userId", required = false) String userId, @RequestParam(value = "jingdu", required = false) String jingdu, @RequestParam(value = "weidu", required = false) String weidu) {
        log.info("StoreInfoController.getStoreDetail?id={},userId={},jingdu={},weidu={}", id, jingdu, weidu);
        StoreInfoVo storeDetail = storeInfoService.getStoreDetail(id, userId, jingdu, weidu);
        return R.data(storeDetail);
    }

    @ApiOperation(value = "获取门店代金券明细")
    @ApiOperationSupport(order = 7)
    @GetMapping("/getStoreCouponList")
    @ResponseBody
    public R getStoreCouponList(@RequestParam("storeId") String storeId) {
        log.info("StoreInfoController.getStoreCouponList?storeId={}", storeId);
        if(storeId == null){
            return R.fail("storeId错误,不能为null,请联系管理员检查");
        }
        CouponAndEventVo couponAndEventVo = new CouponAndEventVo();
//        List<LifeCouponVo> lifeCouponVos = storeInfoService.getStoreCouponList(storeId);

        List<StoreImg> storeImgs = storeInfoService.getBannerUrl(storeId);
//        couponAndEventVo.setCouponList(lifeCouponVos);
        if (CollectionUtils.isNotEmpty(storeImgs)) {
            couponAndEventVo.setMarketingList(storeImgs);
        }
        couponAndEventVo.setMarketingList(storeImgs);
        return R.data(couponAndEventVo);
    }

    @ApiOperation(value = "web端审批店铺")
    @ApiOperationSupport(order = 6)
    @GetMapping("/approveStoreInfo")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "approvalStatus", value = "审批状态（1：审批成功，2：审批失败）", dataType = "int", paramType = "query"), @ApiImplicitParam(name = "reason", value = "原因", dataType = "String", paramType = "query")})
    public R approveStoreInfo(@RequestParam("id") String id, @RequestParam("approvalStatus") Integer approvalStatus, @RequestParam(value = "reason", required = false) String reason) {
        log.info("StoreInfoController.approveStoreInfo?id={}&approvalStatus={}&reason={}", id, approvalStatus, reason);
        storeInfoService.approveStoreInfo(id, approvalStatus, reason);
        return R.success("审批完成");
    }

    @ApiOperation(value = "web端人工复核店铺")
    @ApiOperationSupport(order = 24)
    @PostMapping("/manualReview")
    public R<Boolean> manualReview(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.manualReview?storeInfoDto={}", storeInfoDto);
        try {
            boolean success = storeInfoService.manualReview(storeInfoDto);
            if (success) {
                return R.success("人工复核保存成功");
            }
            return R.fail("人工复核保存失败");
        } catch (IllegalArgumentException e) {
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("StoreInfoController.manualReview ERROR", e);
            return R.fail("人工复核失败");
        }
    }

    @ApiOperation(value = "web端人工复核举报")
    @ApiImplicitParams({@ApiImplicitParam(name = "reportId", value = "举报ID", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "类型（状态(0：待处理，1：已通过，2：已驳回)）", dataType = "int", paramType = "query")})
    @GetMapping("/manualReviewReport")
    public R<Boolean> manualReviewReport(@RequestParam("reportId") Integer reportId, @RequestParam("type") Integer type) {
        log.info("StoreInfoController.manualReviewReport?reportId={}&type={}", reportId, type);
        try {
            boolean success = storeInfoService.manualReviewReport(reportId,type);
            if (success) {
                return R.success("人工复核保存成功");
            }
            return R.fail("人工复核保存失败");
        } catch (IllegalArgumentException e) {
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("StoreInfoController.manualReview ERROR", e);
            return R.fail("人工复核失败");
        }
    }

    @ApiOperation(value = "中台web端获取店铺明细详情")
    @ApiOperationSupport(order = 21)
    @GetMapping("/getNewStoreDetail")
    @ResponseBody
    public R getNewStoreDetail(@RequestParam("id") String id) {
        log.info("StoreInfoController.getStoreDetail?id={}", id);
        StoreInfoVo storeDetail = storeInfoService.getNewStoreDetail(id);
        return R.data(storeDetail);
    }

    @ApiOperation("新中台web端修改门店")
    @ApiOperationSupport(order = 22)
    @PostMapping("/editNewStoreInfo")
    public R editNewStoreInfo(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.editStoreInfo?storeInfoDto={}", storeInfoDto);
        StoreInfoVo storeInfoVo = storeInfoService.editNewStoreInfo(storeInfoDto);
        if (storeInfoVo != null) {
            return R.data(storeInfoVo);
        }
        return R.fail("失败");
    }

    @ApiOperation(value = "web端导出店铺信息")
    @ApiOperationSupport(order = 6)
    @GetMapping("/exportExcel")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storePhone", value = "联系电话", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storeApplicationStatus", value = "审核状态", dataType = "String", paramType = "query"),})
    public R exportExcel(@RequestParam(value = "id", required = false) String id, @RequestParam(value = "storePhone", required = false) String storePhone, @RequestParam(value = "businessSection", required = false) String businessSection, @RequestParam(value = "storeApplicationStatus", required = false) String storeApplicationStatus) throws IOException {
        log.info("StoreInfoController.exportExcel");
        String excelPath = storeInfoService.exportExcel(id, storePhone, businessSection, storeApplicationStatus);
        return R.data(excelPath);
    }

    @ApiOperation(value = "web端导出商铺到期时间信息")
    @ApiOperationSupport(order = 6)
    @GetMapping("/exportExcelExpirationTime")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storePhone", value = "联系电话", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "storeApplicationStatus", value = "审核状态", dataType = "String", paramType = "query"),})
    public R exportExcelExpirationTime(@RequestParam(value = "id", required = false) String id, @RequestParam(value = "expiredState", required = false) String expiredState) throws IOException {
        log.info("StoreInfoController.exportExcelExpirationTime");
        String excelPath = storeInfoService.exportExcelExpirationTime(id, expiredState);
        return R.data(excelPath);
    }

    @ApiOperation(value = "注销店铺")
    @ApiOperationSupport(order = 14)
    @PostMapping("/logoutStore")
    public R logoutStore(@RequestBody StoreInfoVo storeInfo) {
        log.info("StoreInfoController.logoutStore?storeInfo={}", storeInfo);
        // 2025-11-04 验证码-商家端注销店铺
        String cacheCode = baseRedisService.getString("verification_store_cancel_store_" + storeInfo.getStorePhone());
        if (null == cacheCode) {
            return R.fail("当验证码过期或未发送");
        }
        if (!cacheCode.trim().equals(storeInfo.getVerificationCode().trim())) {
            return R.fail("验证码错误，请重新输入");
        }
        try {
            storeInfoService.logoutStore(storeInfo);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.success("注销成功");
    }

    @ApiOperation(value = "取消注销店铺")
    @ApiOperationSupport(order = 15)
    @PostMapping("/cancelLogoutStore")
    public R cancelLogoutStore(@RequestBody StoreInfoVo storeInfo) {
        log.info("StoreInfoController.cancelLogoutStore?id={}", storeInfo.getId());
        try {
            storeInfoService.cancelLogoutStore(storeInfo);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.success("撤销注销成功");
    }

    @ApiOperation(value = "商家注销列表", notes = "中台系统管理-商家管理-商家注销列表，数据源 store_user")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", defaultValue = "1"),
            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "int", paramType = "query", defaultValue = "10"),
            @ApiImplicitParam(name = "userName", value = "用户名（store_user.name）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "logoutFlag", value = "注销标记：1已注销，2注销冷静期", dataType = "int", paramType = "query")
    })
    @GetMapping("/store_user")
    public R<IPage<StoreUserLogoutListVo>> getStoreUserLogoutPage(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String userName,
            @RequestParam(required = false) String phone,
            @RequestParam(required = false) Integer logoutFlag) {
        log.info("StoreInfoController.getStoreUserLogoutPage?pageNum={},pageSize={},userName={},phone={},logoutFlag={}",
                pageNum, pageSize, userName, phone, logoutFlag);
        return R.data(storeUserService.getStoreUserLogoutPage(pageNum, pageSize, userName, phone, logoutFlag));
    }

    /**
     * 八大类用户端筛选
     * 根据筛选条件获取门店信息列表
     *
     * @param screeningOfEightMajorCategoriesVO 筛选条件VO对象
     * @return R<IPage < StoreInfo>> 分页的门店信息列表
     */
    @ApiOperation("八大类用户端筛选")
    @PostMapping(value = "getScreening")
    public R<IPage<StoreInfo>> getScreening(@RequestBody ScreeningOfEightMajorCategoriesVO screeningOfEightMajorCategoriesVO) {
        // 参数校验
        if (screeningOfEightMajorCategoriesVO == null) {
            return R.fail("筛选参数不能为空");
        }
        // 记录请求日志
        log.info("八大类用户端筛选请求 - 参数: screeningId={}, lon={}, lat={}, distance={}, flag={}, pageNum={}, pageSize={}", screeningOfEightMajorCategoriesVO.getScreeningId(), screeningOfEightMajorCategoriesVO.getLon(), screeningOfEightMajorCategoriesVO.getLat(), screeningOfEightMajorCategoriesVO.getDistance(), screeningOfEightMajorCategoriesVO.getFlag(), screeningOfEightMajorCategoriesVO.getPageNum(), screeningOfEightMajorCategoriesVO.getPageSize());
        try {
            // 调用服务层获取筛选结果
            IPage<StoreInfo> result = storeInfoService.getScreening(screeningOfEightMajorCategoriesVO);
            // 记录响应日志
            log.info("八大类用户端筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}", result.getTotal(), result.getCurrent(), result.getSize());
            return R.data(result);
        } catch (IllegalArgumentException e) {
            log.warn("八大类用户端筛选参数错误: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("八大类用户端筛选异常", e);
            return R.fail("筛选失败，请稍后重试");
        }
    }

    /**
     * 新八大类用户端筛选
     * 根据筛选条件获取门店信息列表
     *
     * @param screeningOfEightMajorCategoriesVO 筛选条件VO对象
     * @return R<IPage < StoreInfo>> 分页的门店信息列表
     */
    @ApiOperation("新八大类用户端筛选")
    @PostMapping(value = "getScreeningNew")
    public R<IPage<StoreInfoVo>> getScreeningNew(@RequestBody ScreeningOfEightMajorCategoriesVO screeningOfEightMajorCategoriesVO) {
        // 参数校验
        if (screeningOfEightMajorCategoriesVO == null) {
            return R.fail("筛选参数不能为空");
        }
        // 记录请求日志
        log.info("新八大类用户端筛选请求 - 参数: screeningId={}, lon={}, lat={}, distance={}, flag={}, pageNum={}, pageSize={}", screeningOfEightMajorCategoriesVO.getScreeningId(), screeningOfEightMajorCategoriesVO.getLon(), screeningOfEightMajorCategoriesVO.getLat(), screeningOfEightMajorCategoriesVO.getDistance(), screeningOfEightMajorCategoriesVO.getFlag(), screeningOfEightMajorCategoriesVO.getPageNum(), screeningOfEightMajorCategoriesVO.getPageSize());
        try {
            // 调用服务层获取筛选结果
            IPage<StoreInfoVo> result = storeInfoService.getScreeningNew(screeningOfEightMajorCategoriesVO);
            // 记录响应日志
            log.info("新八大类用户端筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}", result.getTotal(), result.getCurrent(), result.getSize());

            return R.data(result);
        } catch (IllegalArgumentException e) {
            log.warn("新八大类用户端筛选参数错误: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("新八大类用户端筛选异常", e);
            return R.data(null);
            //return R.fail("筛选失败，请稍后重试");
        }
    }


    /**
     * 八大类用户端经营类型筛选
     *
     * @param businessTypesNames 经营类型名称，多个类型用逗号分隔
     * @return R<List < StoreInfo>> 筛选结果
     */
    @ApiOperation("八大类用户端经营类型筛选")
    @ApiOperationSupport(order = 13)
    @ApiImplicitParams({@ApiImplicitParam(name = "businessTypesNames", value = "经营类型名称，多个类型用逗号分隔", dataType = "String", paramType = "query")})
    @GetMapping(value = "getBusinessTypesName")
    public R<List<StoreInfo>> getBusinessTypesName(@RequestParam(value = "businessTypesNames", required = false) String businessTypesNames) {
        log.info("StoreInfoController.getBusinessTypesName?businessTypesNames={}", businessTypesNames);
        try {
            List<StoreInfo> result = storeInfoService.getBusinessTypesName(businessTypesNames);
            return R.data(result);
        } catch (Exception e) {
            log.error("八大类用户端经营类型筛选失败", e);
            return R.fail("筛选失败：" + e.getMessage());
        }
    }

    /**
     * web-查询店铺信息根据门店电话
     *
     * @param storeTel 门店电话
     * @return R
     */
    @ApiOperation("web-查询店铺信息根据门店电话")
    @ApiOperationSupport(order = 14)
    @GetMapping("/getStoreInfoByStoreTel")
    public R<List<StoreInfo>> getStoreInfoByCreateUser(@RequestParam(value = "storeTel") String storeTel) {
        log.info("StoreInfoController.getStoreInfoByStoreTel?storeTel={}", storeTel);
        return R.data(storeInfoService.getStoreInfoByStoreTel(storeTel));
    }

    /**
     * 商家端注销店铺效验
     *
     * @param id 门店id
     */
    @ApiOperation("商家端注销店铺效验")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/storeInfoVerification")
    public R<Map<String, String>> storeInfoVerification(int id) {
        log.info("StoreInfoController.storeInfoVerification?id={}", id);
        return R.data(storeInfoService.storeInfoVerification(id));
    }

    /**
     * 手动删除店铺
     */
    @ApiOperation("手动删除店铺")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/deleteManualStoreInfo")
    public R<StoreUserVo> deleteManualStoreInfo(int id) {
        log.info("StoreUserController.deleteManualStoreInfo?id={}", id);
        storeInfoService.deleteManualStoreInfo(id);
        return R.success("删除成功");
    }

    @ApiOperation(value = "门店装修-详细信息")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "Long", paramType = "query", required = true)})
    @GetMapping("/getDecorationDetail")
    public R<StoreMainInfoVo> getDecorationDetail(Integer id) {
        log.info("StoreInfoController.getDecorationDetail?id={}", id);
        return R.data(storeInfoService.getDecorationDetail(id));
    }

    @ApiOperation(value = "门店装修-门店营业时间")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "Long", paramType = "query", required = true)})
    @GetMapping("/getStoreInfoBusinessHours")
    public R<List<StoreBusinessInfoVo>> getStoreInfoBusinessHours(Integer id) {
        log.info("StoreInfoController.getStoreInfoBusinessHours?id={}", id);
        return R.data(storeInfoService.getStoreInfoBusinessHours(id));
    }

    @ApiOperation(value = "门店装修-续签合同")
    @PostMapping("/uploadRenewalContract")
    public R<String> uploadRenewalContract(@RequestBody List<StoreImg> storeImgList) {
        log.info("StoreInfoController.uploadRenewalContract?storeImgList={}", storeImgList);
        int num = storeInfoService.uploadRenewalContract(storeImgList);
        if (num <= 0) {
            return R.fail("续签合同图片添加失败");
        }
        return R.success("续签合同图片添加成功");
    }

    @ApiOperation(value = "门店装修-续签合同状态及合同图片")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getStoreContractStatus")
    public R<Map<String, Object>> getStoreContractStatus(int id) {
        log.info("StoreInfoController.getStoreContractStatus?id={}", id);
        return R.data(storeInfoService.getStoreContractStatus(id));
    }

    @ApiOperation(value = "门店装修-审核续签合同状态")
    @PostMapping("/updateContractImageStatus")
    public R<String> updateContractImageStatus(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.updateContractImageStatus?storeInfoDto={}", storeInfoDto);
        StoreInfo storeInfo = storeInfoService.getOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, storeInfoDto.getId()));
        if (storeInfo != null) {
            if (storeInfoDto.getRenewContractStatus() == 3) {
                storeInfo.setContractReason(storeInfoDto.getContractReason());
                storeInfo.setRenewContractStatus(storeInfoDto.getRenewContractStatus());
                boolean flag = storeInfoService.updateById(storeInfo);
                if (flag) {
                    return R.success("拒绝审核成功");
                } else {
                    return R.fail("拒绝审核失败");
                }
            }
            storeInfo.setRenewContractStatus(storeInfoDto.getRenewContractStatus());
            storeInfo.setContractReason(storeInfoDto.getContractReason());
            boolean flag = storeInfoService.updateById(storeInfo);
            if (flag) {
                //审核通过后删除原店铺合同 续签合同类型变为合同
                int num = storeInfoService.conversionContract(storeInfoDto.getId());
                if (num > 0) {
                    return R.success("审核通过成功");
                } else {
                    return R.fail("审核通过失败");
                }
            }
        }
        return R.fail("审核失败 店铺不存在");
    }

    @ApiOperation(value = "门店装修-食品经营许可证")
    @PostMapping("/uploadfoodLicence")
    public R<String> uploadfoodLicence(@RequestBody StoreImg storeImg) {
        log.info("StoreInfoController.uploadfoodLicence?storeImg={}", storeImg);
        int num = storeInfoService.uploadfoodLicence(storeImg);
        if (num > 0) {
            WebAudit webAudit = new WebAudit();
            webAudit.setStoreInfoId(storeImg.getStoreId().toString());
            webAudit.setType("7");
            webAudit.setStatus("0");
            webAudit.setContent("经营许可证");
            webAuditMapper.insert(webAudit);
            return R.success("食品经营许可证图片添加成功");
        }
        return R.fail("食品经营许可证图片添加失败");
    }

    @ApiOperation(value = "门店装修-食品经营许可证状态及合同图片")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getStoreFoodLicenceStatus")
    public R<Map<String, Object>> getStoreFoodLicenceStatus(int id) {
        log.info("StoreInfoController.getStoreFoodLicenceStatus?id={}", id);
        return R.data(storeInfoService.getStoreFoodLicenceStatus(id));
    }

    @ApiOperation(value = "查看营业执照（返回图片和到期时间）")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getBusinessLicenseStatus")
    public R<Map<String, Object>> getBusinessLicenseStatus(int id) {
        log.info("StoreInfoController.getBusinessLicenseStatus?id={}", id);
        return R.data(storeInfoService.getBusinessLicenseStatus(id));
    }

    @ApiOperation(value = "更换营业执照")
    @PostMapping("/uploadBusinessLicense")
    public R<String> uploadBusinessLicense(@RequestBody StoreImg storeImg) {
        log.info("StoreInfoController.uploadBusinessLicense?storeImg={}", storeImg);
        try {
            int num = storeInfoService.uploadBusinessLicense(storeImg);
            if (num > 0) {
                return R.success("更换成功,请耐心等待审核");
            }
            return R.fail("营业执照更换失败");
        } catch (Exception e) {
            log.error("更换营业执照异常", e);
            return R.fail("营业执照更换失败：" + e.getMessage());
        }
    }

    @ApiOperation(value = "查看营业执照变更记录")
    @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getBusinessLicenseHistory")
    public R<List<StoreLicenseHistory>> getBusinessLicenseHistory(@RequestParam("storeId") Integer storeId) {
        log.info("StoreInfoController.getBusinessLicenseHistory?storeId={}", storeId);
        return R.data(storeInfoService.getBusinessLicenseHistory(storeId));
    }

    @ApiOperation(value = "查看其他资质证明（返回图片列表）")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getOtherQualificationStatus")
    public R<Map<String, Object>> getOtherQualificationStatus(int id) {
        log.info("StoreInfoController.getOtherQualificationStatus?id={}", id);
        return R.data(storeInfoService.getOtherQualificationStatus(id));
    }

    @ApiOperation(value = "更换其他资质证明")
    @PostMapping("/uploadOtherQualification")
    public R<String> uploadOtherQualification(@RequestBody List<StoreImg> storeImgList) {
        log.info("StoreInfoController.uploadOtherQualification?storeImgList={}", storeImgList);
        try {
            int num = storeInfoService.uploadOtherQualification(storeImgList);
            if (num > 0) {
                return R.success("更换成功,请耐心等待审核");
            }
            return R.fail("其他资质证明更换失败");
        } catch (Exception e) {
            log.error("更换其他资质证明异常", e);
            return R.fail("其他资质证明更换失败：" + e.getMessage());
        }
    }

    @ApiOperation(value = "查看其他资质证明变更记录")
    @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query", required = true)})
    @GetMapping("/getOtherQualificationHistory")
    public R<List<StoreLicenseHistory>> getOtherQualificationHistory(@RequestParam("storeId") Integer storeId) {
        log.info("StoreInfoController.getOtherQualificationHistory?storeId={}", storeId);
        return R.data(storeInfoService.getOtherQualificationHistory(storeId));
    }

    @ApiOperation(value = "门店装修-审核食品经营许可证状态")
    @PostMapping("/updatefoodLicenceImageStatus")
    @Transactional(rollbackFor = Exception.class)
    public R<String> updatefoodLicenceImageStatus(@RequestBody StoreInfoDto storeInfoDto) {
        log.info("StoreInfoController.updatefoodLicenceImageStatus?storeInfoDto={}", storeInfoDto);
        StoreInfo storeInfo = storeInfoService.getOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, storeInfoDto.getId()));
        if (storeInfo != null) {
            if (storeInfoDto.getFoodLicenceStatus() == 3) {
                storeInfo.setFoodLicenceReason(storeInfoDto.getFoodLicenceReason());
                storeInfo.setFoodLicenceStatus(storeInfoDto.getFoodLicenceStatus());
                boolean flag = storeInfoService.updateById(storeInfo);
                if (flag) {
                    // 审核拒绝时修改提交记录
                    LambdaUpdateWrapper<StoreLicenseHistory> wrapper = new LambdaUpdateWrapper<>();
                    wrapper.eq(StoreLicenseHistory::getStoreId, storeInfo.getId());
                    wrapper.eq(StoreLicenseHistory::getLicenseStatus, 2);
                    wrapper.eq(StoreLicenseHistory::getLicenseExecuteStatus, 2);
                    wrapper.set(StoreLicenseHistory::getLicenseExecuteStatus, 3);
                    wrapper.set(StoreLicenseHistory::getReasonRefusal, storeInfoDto.getFoodLicenceReason());
                    wrapper.set(StoreLicenseHistory::getDeleteFlag, 1);
                    licenseHistoryMapper.update(null, wrapper);

                    //待审核状态变为已审核
                    WebAudit webAudit = webAuditMapper.selectOne(new LambdaQueryWrapper<WebAudit>().eq(WebAudit::getStoreInfoId, storeInfo.getId()).eq(WebAudit::getDeleteFlag, 0).eq(WebAudit::getType, "7"));
                    if (webAudit != null) {
                        webAudit.setStatus("1");
                        webAuditMapper.updateById(webAudit);
                    }
                    return R.success("拒绝审核成功");
                } else {
                    return R.fail("拒绝审核失败");
                }
            }
            storeInfo.setFoodLicenceReason(storeInfoDto.getFoodLicenceReason());
            storeInfo.setFoodLicenceStatus(storeInfoDto.getFoodLicenceStatus());
            boolean flag = storeInfoService.updateById(storeInfo);
            if (flag) {
                int num = storeInfoService.foodLicenceType(storeInfoDto.getId());
                if (num > 0) {
                    //待审核状态变为已审核
                    WebAudit webAudit = webAuditMapper.selectOne(new LambdaQueryWrapper<WebAudit>()
                            .eq(WebAudit::getStoreInfoId, storeInfo.getId())
                            .eq(WebAudit::getDeleteFlag, 0)
                            .eq(WebAudit::getType, "7")
                            .eq(WebAudit::getStatus,0));
                    if (webAudit != null) {
                        webAudit.setStatus("1");
                        webAuditMapper.updateById(webAudit);
                    }
                }
                return R.success("审核通过成功");
            } else {
                return R.fail("审核失败");
            }
        }
        return R.fail("审核失败 店铺不存在");
    }

    @ApiOperation(value = "AI服务-门店评价标签")
    @GetMapping("/getStoreEvaluateTags")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query", required = true)
    })
    public R<Map<String,Object>> getStoreEvaluateTags(@RequestParam("storeId") int storeId) {
        log.info("StoreInfoController.getStoreEvaluateTags?storeId={}, tagType={}", storeId);
        Map<String,Object> map = new HashMap<>();
        List<TagsMainVo> voList = tagsMainMapper.getStoreEvaluateTags(storeId);
//        if(voList !=null && voList.size()>0){
            StoreCommentVo storeComment = storeCommentMapper.getCommentOneInfo(storeId);
            if(storeComment!=null){
                if(storeComment.getImgId()!=null){
                    List<String> imgIds = Arrays.asList(storeComment.getImgId().split(","));
                    List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, imgIds));
                    storeComment.setImgList(storeImgs);
                }
                LambdaQueryWrapper<StoreComment> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(StoreComment :: getStoreId, storeId);
                lambdaQueryWrapper1.eq(StoreComment :: getBusinessType, 6);
                lambdaQueryWrapper1.eq(StoreComment :: getDeleteFlag, 0);
                Integer commitCount = storeCommentMapper.selectCount(lambdaQueryWrapper1);
                map.put("commitCount",commitCount);
            }
            map.put("tag",voList);
            map.put("evaluate",storeComment);
//        }
        return R.data(map);
    }

    @ApiOperation(value = "AI服务-门店评价标签下评价")
    @GetMapping("/getStoreEvaluateTagsList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mainId", value = "标签id", dataType = "int", paramType = "query", required = true)
    })
    public R<List<StoreCommentVo>> getStoreEvaluateTagsList(@RequestParam("mainId") int mainId) {
        log.info("StoreInfoController.getStoreEvaluateTagsList?mainId={}", mainId);
        List<StoreCommentVo> list = tagsMainMapper.getstoreCommentList(mainId);
        if(list!=null && list.size()>0){
            for(int i = 0; i<list.size(); i++){
                if(list.get(i).getImgId()!=null){
                    List<String> imgIds = Arrays.asList(list.get(i).getImgId().split(","));
                    List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, imgIds));
                    list.get(i).setImgList(storeImgs);
                }
            }
        }
        return R.data(list);
    }
    @ApiOperation(value = "AI服务-门店趣味信息")
    @GetMapping("/getStoreInterestInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query")
    })
    public R<List<StoreCommentSummaryInterest>> getStoreInterestInfo(int storeId) {
        log.info("StoreInfoController.getStoreInterestInfo?storeId={}", storeId);
        List<StoreCommentSummaryInterest> list = storeCommentSummaryInterestMapper.selectList(
                new LambdaQueryWrapper<StoreCommentSummaryInterest>()
                        .eq(StoreCommentSummaryInterest::getStoreId, storeId)
                        .last("ORDER BY RAND() LIMIT 1") // 随机排序并只取第一条
        );
        return R.data(list);
    }

    @ApiOperation(value = "门店趣味信息-打卡方式")
    @GetMapping("/getStoreClockIn")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "int", paramType = "query")
    })
    public R<List<StoreClockInVo>> getStoreClockIn(int storeId) {
        log.info("StoreInfoController.getStoreClockIn?storeId={}", storeId);
        List<StoreClockIn> list = storeClockInMapper.selectList(
                new LambdaQueryWrapper<StoreClockIn>()
                        .eq(StoreClockIn::getStoreId, storeId)
                        .isNotNull(StoreClockIn::getMaybeAiContent)
                        .last("ORDER BY RAND() LIMIT 1") // 随机排序并只取第一条
        );
        List result= new ArrayList<>();
        if( list.size()>0) {
            StoreClockInVo  storeClockInVo = new StoreClockInVo();
            BeanUtils.copyProperties(list.get(0), storeClockInVo);
            clockInIdentityHelper.ensureEntityLegacyPhoneId(storeClockInVo);
            LifeUser lifeUser = lifeUserMapper.selectById(list.get(0).getUserId());
            storeClockInVo.setUserImg(lifeUser.getUserImage());
            result.add(storeClockInVo);
        }
        return R.data(result);
    }


    @ApiOperation(value = "AI服务-店铺审核")
    @ApiOperationSupport(order = 15)
    @PostMapping("/aiApproveStoreInfo")
    public R<AiApproveStoreInfoResultVo> aiApproveStoreInfo(@RequestBody AiApproveStoreInfo aiApproveStoreInfo) {
        log.info("StoreInfoController.aiApproveStoreInfo");
        try {
            AiApproveStoreInfoResultVo result = storeInfoService.aiApproveStoreInfo(aiApproveStoreInfo);
            return R.data(result, "店铺审核完成");
        } catch (Exception e) {
            log.error("AI服务-店铺审核异常", e);
            return R.fail("店铺审核失败：" + e.getMessage());
        }
    }

    @ApiOperation(value = "更多推荐（用户端）")
    @GetMapping("/getMoreRecommendedStores")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lon", value = "经度", dataType = "double", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "double", paramType = "query", required = true),
            @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "businessTypes", value = "经营分类", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "businessClassify", value = "分类", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeId", value = "当前商铺ID（传入则从推荐列表中排除该店铺）", dataType = "Integer", paramType = "query")
    })
    public R<List<StoreInfoVo>> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify,
                                                        @RequestParam(required = false) Integer storeId) {
        log.info("StoreInfoController.getMoreRecommendedStores?lon={},lat={},businessSection={},businessTypes={},businessClassify={},storeId={}", lon,lat, businessSection, businessTypes, businessClassify, storeId);
        return R.data(storeInfoService.getMoreRecommendedStores(lon,lat, businessSection, businessTypes, businessClassify, storeId));

    }

    @ApiOperation(value = "根据店铺ID获取推荐店铺列表（用户端）")
    @GetMapping("/getRecommendedStoresByStoreId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = true)
    })
    public R<List<StoreInfoVo>> getRecommendedStoresByStoreId(@RequestParam Integer storeId) {
        log.info("StoreInfoController.getRecommendedStoresByStoreId?storeId={}", storeId);
        try {
            if (storeId == null || storeId <= 0) {
                log.warn("获取推荐店铺列表失败，店铺ID无效：{}", storeId);
                return R.fail("店铺ID不能为空且必须大于0");
            }
            List<StoreInfoVo> result = storeInfoService.getRecommendedStoresByStoreId(storeId);
            log.info("获取推荐店铺列表成功，storeId={}，返回店铺数量：{}", storeId, result != null ? result.size() : 0);
            return R.data(result);
        } catch (Exception e) {
            log.error("获取推荐店铺列表异常，storeId={}，异常信息：{}", storeId, e.getMessage(), e);
            return R.fail("获取推荐店铺列表失败：" + e.getMessage());
        }
    }

    @ApiOperation(value = "AI服务-门头识别")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "imageUrl", value = "图片URL", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "merchantName", value = "门店名称", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/getStoreOcrData")
    public R<Map<String, Object>> getStoreOcrData(@RequestParam("imageUrl") String imageUrl,
                                                  @RequestParam("merchantName") String merchantName) {
        log.info("StoreInfoController.getStoreOcrData?imageUrl={},merchantName{}", imageUrl, merchantName);
        if (merchantName == null || merchantName.trim().isEmpty() || imageUrl == null || imageUrl.trim().isEmpty()) {
            return R.fail("门店名称与图片URL不能为空");
        }
        Map<String, Object> ocrData = null;
        try {
            ocrData = storeInfoService.getStoreOcrData(imageUrl, merchantName);
        } catch (Exception e) {
            return R.fail("未查询到OCR识别数据");
        }
        return R.data(ocrData);
    }

    @ApiOperation(value = "获取店铺详情（用户端）")
    @ApiOperationSupport(order = 17)
    @GetMapping("/getClientStoreDetail")
    @ResponseBody
    public R getClientStoreDetail(@RequestParam("id") String id,
                                  @RequestParam(value = "userId", required = false) String userId,
                                  @RequestParam(value = "jingdu", required = false) String jingdu,
                                  @RequestParam(value = "weidu", required = false) String weidu) {
        log.info("StoreInfoController.getClientStoreDetail?id={},userId={},jingdu={},weidu={}", id, userId, jingdu, weidu);
        StoreInfoVo storeDetail = storeInfoService.getClientStoreDetail(id, userId, jingdu, weidu);
        return R.data(storeDetail);
    }

    @ApiOperation(value = "获取店铺营业状态", notes = "判断店铺当前是否在营业时间内，返回营业状态和营业时间信息")
    @ApiOperationSupport(order = 17)
    @GetMapping("/getStoreBusinessStatus")
    @ResponseBody
    public R<StoreBusinessStatusVo> getStoreBusinessStatus(@RequestParam("id") String id) {
        log.info("StoreInfoController.getStoreBusinessStatus?id={}", id);
        StoreBusinessStatusVo businessStatus = storeInfoService.getStoreBusinessStatus(id);
        return R.data(businessStatus);
    }

    @ApiOperation(value = "查询当前门店的资质信息", notes = "查询营业执照和其他资质证明图片")
    @ApiOperationSupport(order = 18)
    @GetMapping("/getStoreQualificationInfo")
    @ResponseBody
    public R<StoreQualificationInfoVo> getStoreQualificationInfo(@RequestParam("storeId") Integer storeId) {
        log.info("StoreInfoController.getStoreQualificationInfo?storeId={}", storeId);
        StoreQualificationInfoVo qualificationInfo = storeQualificationService.getStoreQualificationInfo(storeId);
        return R.data(qualificationInfo);
    }
    /**
     * 查询四种类型店铺（酒吧、ktv、洗浴汗蒸、按摩足浴）并按距离筛选
     *
     * @param lon         经度
     * @param lat         纬度
     * @param distance    距离范围（单位：公里）
     * @param sortType    排序模式（1:智能排序，2:好评优先，3:距离优先）
     * @param businessType 店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧需要查询字典表），可选，如果指定则只查询该类型
     * @param pageNum     页码
     * @param pageSize    页容
     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
     */
    @ApiOperation("查询四种类型店铺（酒吧、ktv、洗浴汗蒸、按摩足浴）并按距离筛选")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "distance", value = "距离范围（单位：公里）", dataType = "Double", paramType = "query"),
            @ApiImplicitParam(name = "sortType", value = "排序模式（1:智能排序，2:好评优先，3:距离优先）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "businessType", value = "店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，丽人美发=6，运动健身=7，酒吧=11）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "categoryId", value = "字典表id，根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "storeName", value = "店铺名称（模糊查询）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeType", value = "美食3 休闲娱乐1  健身2 ", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
    })
    @GetMapping("/getSpecialTypeStoresByDistance")
    public R<IPage<StoreInfoVo>> getSpecialTypeStoresByDistance(
            @RequestParam("lon") Double lon,
            @RequestParam("lat") Double lat,
            @RequestParam(value = "distance", required = false) Double distance,
            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
            @RequestParam(value = "businessType", required = false) Integer businessType,
            @RequestParam(value = "categoryId", required = false) Integer categoryId,
            @RequestParam(value = "storeName", required = false) String storeName,
            @RequestParam(value = "storeType", required = false) Integer storeType,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize) {
        log.info("StoreInfoController.getSpecialTypeStoresByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},storeName={},storeType{},pageNum={},pageSize={}",
                lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);

        try {
            // 参数校验：经度范围 [-180, 180]，纬度范围 [-90, 90]
            if (lon == null || lat == null) {
                return R.fail("经纬度参数不能为空");
            }

            // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
                return R.fail(String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
            }

            if (lon < -180 || lon > 180) {
                return R.fail("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
            }
            if (lat < -90 || lat > 90) {
                return R.fail("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
            }

            // 调用服务层获取筛选结果
            IPage<StoreInfoVo> result = storeInfoService.getSpecialTypeStoresByDistance(lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);

            // 记录响应日志
            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
                    result.getTotal(), result.getCurrent(), result.getSize());

            return R.data(result);
        } catch (IllegalArgumentException e) {
            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("四种类型店铺距离筛选异常", e);
            return R.fail("筛选失败，请稍后重试");
        }
    }



    /**
     * 获取休闲娱乐分类数据（主分类和子分类）
     * 根据图片需求，返回层级结构的分类数据
     *
     * @return R<List<StoreDictionaryVo>> 分类列表，包含主分类和子分类
     */
    @ApiOperation("获取休闲娱乐分类数据（主分类和子分类）")
    @ApiOperationSupport(order = 18)
    @GetMapping("/getLeisureEntertainmentCategories")
    public R<List<StoreDictionaryVo>> getLeisureEntertainmentCategories() {
        log.info("StoreInfoController.getLeisureEntertainmentCategories");
        try {
            List<StoreDictionaryVo> result = storeInfoService.getLeisureEntertainmentCategories();
            return R.data(result);
        } catch (Exception e) {
            log.error("获取休闲娱乐分类数据异常", e);
            return R.fail("获取分类数据失败，请稍后重试");
        }
    }

    /**
     * 获取休闲娱乐分类数据（主分类和子分类）
     * 根据图片需求，返回层级结构的分类数据
     *getAllBusinessSection
     * @return R<List<StoreDictionary>> 分类列表，包含主分类和子分类
     */


    @ApiOperation("获取所有经营板块以及子类")
    @ApiOperationSupport(order = 18)
    @GetMapping("/getAllBusinessSection")
    public R<List<StoreDictionary>> queryBusinessSectionTree(
            @ApiParam(value = "一级分类dictId，可选，如果传入则只返回该一级分类下的二级和三级分类", required = false)
            @RequestParam(required = false) String businessSection) {
        log.info("platformBusinessSection.queryBusinessSectionTree, businessSection={}", businessSection);

        try {
            List<StoreDictionary> result = storeInfoService.getAllBusinessSection(businessSection);
            return R.data(result);
        }catch (Exception e){
            log.error("获取休闲娱乐分类数据异常", e);
            return R.fail("获取分类数据失败，请稍后重试");
        }

    }



    /**
     * 你可能还喜欢（推荐店铺）
     * 根据一级分类、二级分类、三级分类进行店铺筛选
     * 筛选顺序：先三级，然后二级，最后一级
     *
     * @param businessSection 一级分类（经营板块）
     * @param businessTypes 二级分类（经营种类）
     * @param businessClassify 三级分类（分类）
     * @param lon 经度
     * @param lat 纬度
     * @return R<List<StoreInfoVo>> 店铺信息列表
     */
    @ApiOperation("你可能还喜欢（推荐店铺）")
    @ApiOperationSupport(order = 19)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "businessSection", value = "一级分类（经营板块）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "businessTypes", value = "二级分类（经营种类）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "businessClassify", value = "三级分类（分类）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query"),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query")
    })
    @GetMapping("/getRecommendedStores")
    public R<List<StoreInfoVo>> getRecommendedStores(
            @RequestParam(value = "businessSection", required = true) String businessSection,
            @RequestParam(value = "businessTypes", required = false) String businessTypes,
            @RequestParam(value = "businessClassify", required = false) String businessClassify,
            @RequestParam(value = "lon", required = false) Double lon,
            @RequestParam(value = "lat", required = false) Double lat) {
        log.info("StoreInfoController.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}",
                businessSection, businessTypes, businessClassify, lon, lat);
        try {
            List<StoreInfoVo> result = storeInfoService.getRecommendedStores(businessSection, businessTypes, businessClassify, lon, lat);
            return R.data(result);
        } catch (Exception e) {
            log.error("获取推荐店铺异常", e);
            return R.fail("获取推荐店铺失败，请稍后重试");
        }
    }
    /**
     * 根据business_classify字段获取字典表数据实现UI图中的功能
     * RESTful风格：GET /store/info/business-classifies
     * 返回扁平化的分类列表，用于多选分类功能
     *
     * @param parentId 父分类ID（可选），如果提供则只返回该父分类下的子分类
     * @return R<List<StoreDictionaryVo>> 分类列表（扁平化，仅子分类）
     */
    @ApiOperation("获取店铺分类信息）")
    @ApiOperationSupport(order = 19)
    @GetMapping("/business-classifies")
    public R<List<StoreDictionaryVo>> getBusinessClassifyData(
            @RequestParam(value = "parentId", required = false) Integer parentId) {
        log.info("StoreInfoController.getBusinessClassifyData?parentId={}", parentId);
        try {
            List<StoreDictionaryVo> result = storeInfoService.getBusinessClassifyData(parentId);
            return R.data(result);
        } catch (Exception e) {
            log.error("获取business_classify分类数据异常", e);
            return R.fail("获取分类数据失败，请稍后重试");
        }
    }


    @ApiOperation(value = "获取banner图详情")
    @ApiOperationSupport(order = 7)
    @GetMapping("/getBannerUrlInfo")
    @ResponseBody
    public R getBannerUrlInfo(@RequestParam("storeId") String storeId, @RequestParam("businessId") Integer businessId) {
        log.info("StoreInfoController.getBannerUrlInfo?storeId={},businessId{}", storeId, businessId);

        try {

            return R.data(storeInfoService.getBannerUrlInfo(storeId, businessId));

        } catch (Exception e) {

            log.error("StoreInfoController.getBannerUrlInfo ERROR Msg={}", e.getMessage(), e);

            return R.fail("查询失败");
        }

    }


    @ApiOperation(value = "证照查询")
    @ApiOperationSupport(order = 23)
    @GetMapping("/getStoreLicenseList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "storeName", value = "门店名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeContact", value = "联系人", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeTel", value = "门店电话", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "imgType", value = "证照图片类型（14：营业执照；35：其他资质证明）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "states", value = "证照状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "startSubmitDate", value = "提交开始时间（yyyy-MM-dd HH:mm:ss）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endSubmitDate", value = "提交结束时间（yyyy-MM-dd HH:mm:ss）", dataType = "String", paramType = "query")
    })
    public R<IPage<StoreLicenseInfoVo>> getStoreLicenseList(
            @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
            @RequestParam(value = "storeName", required = false) String storeName,
            @RequestParam(value = "storeContact", required = false) String storeContact,
            @RequestParam(value = "storeTel", required = false) String storeTel,
            @RequestParam(value = "businessSection", required = false) String businessSection,
            @RequestParam(value = "imgType", required = false) Integer imgType,
            @RequestParam(value = "states", required = false) String states,
            @RequestParam(value = "startSubmitDate", required = false) String startSubmitDate,
            @RequestParam(value = "endSubmitDate", required = false) String endSubmitDate) {
        log.info("StoreInfoController.getStoreLicenseList?pageNum={},pageSize={},storeName={},storeContact={},storeTel={},businessSection={},imgType={},states={},startSubmitDate={},endSubmitDate={}",
                pageNum, pageSize, storeName, storeContact, storeTel, businessSection, imgType, states, startSubmitDate, endSubmitDate);
        IPage<StoreLicenseInfoVo> page = storeInfoService.getStoreLicenseList(pageNum, pageSize, storeName, storeContact, storeTel, businessSection, imgType, states, startSubmitDate, endSubmitDate);
        return R.data(page);
    }


    /**
     * 查询两种类型店铺（丽人美发、运动健身）并按距离筛选
     *
     * @param lon         经度
     * @param lat         纬度
     * @param distance    距离范围（单位：公里）
     * @param sortType    排序模式（1:智能排序，2:好评优先，3:距离优先）
     * @param businessType 店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，丽人美发=6，运动健身=7），可选，如果指定则只查询该类型
     * @param pageNum     页码
     * @param pageSize    页容
     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
     *
     */
    @ApiOperation("查询两种类型店铺（丽人美发、运动健身）并按距离筛选")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "distance", value = "距离范围（单位：公里）", dataType = "Double", paramType = "query"),
            @ApiImplicitParam(name = "sortType", value = "排序模式（1:智能排序，2:好评优先，3:距离优先）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "businessType", value = "店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，丽人美发=6，运动健身=7，酒吧=11）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "categoryId", value = "字典表id，根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "storeName", value = "商家名称（模糊查询）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
    })
    @GetMapping("/getLifeServicesByDistance")
    public R<IPage<StoreInfoVo>> getLifeServicesByDistance(
            @RequestParam("lon") Double lon,
            @RequestParam("lat") Double lat,
            @RequestParam(value = "distance", required = false) Double distance,
            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
            @RequestParam(value = "businessType", required = false) Integer businessType,
            @RequestParam(value = "categoryId", required = false) Integer categoryId,
            @RequestParam(value = "storeName", required = false) String storeName,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize) {
        log.info("StoreInfoController.getLifeServicesByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},storeName={},pageNum={},pageSize={}",
                lon, lat, distance, sortType, businessType, categoryId, storeName, pageNum, pageSize);

        try {
            // 参数校验：经度范围 [-180, 180]，纬度范围 [-90, 90]
            if (lon == null || lat == null) {
                return R.fail("经纬度参数不能为空");
            }

            // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
                return R.fail(String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
            }

            if (lon < -180 || lon > 180) {
                return R.fail("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
            }
            if (lat < -90 || lat > 90) {
                return R.fail("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
            }

            // 调用服务层获取筛选结果
            IPage<StoreInfoVo> result = storeInfoService.getLifeServicesByDistance(lon, lat, distance, sortType, businessType, categoryId, storeName, pageNum, pageSize);

            // 记录响应日志
            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
                    result.getTotal(), result.getCurrent(), result.getSize());

            return R.data(result);
        } catch (IllegalArgumentException e) {
            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("四种类型店铺距离筛选异常", e);
            return R.fail("筛选失败，请稍后重试");
        }
    }



    /**
     * 查询七种类型店铺（酒吧、ktv、洗浴汗蒸、按摩足浴 、运动健身、丽人美发 、特色美食）并按距离筛选
     *
     * @param lon         经度
     * @param lat         纬度
     * @param distance    距离范围（单位：公里）
     * @param sortType    排序模式（1:智能排序，2:好评优先，3:距离优先）
     * @param businessType 店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧需要查询字典表），可选，如果指定则只查询该类型
     * @param pageNum     页码
     * @param pageSize    页容
     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
     */
    @ApiOperation("查询七种类型店铺（酒吧、ktv、洗浴汗蒸、按摩足浴 、运动健身、丽人美发 、特色美食）并按距离筛选")
    @ApiOperationSupport(order = 16)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
            @ApiImplicitParam(name = "distance", value = "距离范围（单位：公里）", dataType = "Double", paramType = "query"),
            @ApiImplicitParam(name = "sortType", value = "排序模式（1:智能排序，2:好评优先，3:距离优先）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "businessType", value = "店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，丽人美发=6，运动健身=7，酒吧=11）", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "categoryId", value = "字典表id，根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "storeName", value = "店铺名称（模糊查询）", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "storeType", value = "美食3 休闲娱乐1  健身2 ", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
    })
    @GetMapping("/getThreeCategoriesStoresByDistance")
    public R<IPage<StoreInfoVo>> getThreeCategoriesStoresByDistance(
            @RequestParam("lon") Double lon,
            @RequestParam("lat") Double lat,
            @RequestParam(value = "distance", required = false) Double distance,
            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
            @RequestParam(value = "businessType", required = false) Integer businessType,
            @RequestParam(value = "categoryId", required = false) Integer categoryId,
            @RequestParam(value = "storeName", required = false) String storeName,
            @RequestParam(value = "storeType", required = false) Integer storeType,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize) {
        log.info("StoreInfoController.getSpecialTypeStoresByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},storeName={},storeType{},pageNum={},pageSize={}",
                lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);

        try {
            // 参数校验：经度范围 [-180, 180]，纬度范围 [-90, 90]
            if (lon == null || lat == null) {
                return R.fail("经纬度参数不能为空");
            }

            // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
                return R.fail(String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
            }

            if (lon < -180 || lon > 180) {
                return R.fail("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
            }
            if (lat < -90 || lat > 90) {
                return R.fail("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
            }

            // 调用服务层获取筛选结果
            IPage<StoreInfoVo> result = storeInfoService.getThreeCategoriesStoresByDistance(lon, lat, distance, sortType, businessType, categoryId, storeName,storeType, pageNum, pageSize);

            // 记录响应日志
            log.info("七种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
                    result.getTotal(), result.getCurrent(), result.getSize());

            return R.data(result);
        } catch (IllegalArgumentException e) {
            log.warn("七种类型店铺距离筛选参数错误: {}", e.getMessage());
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("七种类型店铺距离筛选异常", e);
            return R.fail("筛选失败，请稍后重试");
        }
    }

    @ApiOperation("分页随机查询店铺（排除已删除、已拉黑和已关注的店铺）")
    @ApiOperationSupport(order = 100)
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "page",
                    value = "页数（默认1）",
                    dataType = "int",
                    paramType = "query"
            ),
            @ApiImplicitParam(
                    name = "size",
                    value = "页容（默认10）",
                    dataType = "int",
                    paramType = "query"
            )
    })
    @GetMapping("/getRandomPage")
    public R<IPage<StoreInfoWithHeadImg>> getRandomPage(
            @ApiIgnore @TokenInfo UserLoginInfo userLoginInfo,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        log.info("StoreInfoController.getRandomPage - page={}, size={}", page, size);
        try {
            // 参数校验
            int pageNum = page > 0 ? page : 1;
            int pageSize = size > 0 ? size : 10;
            
            // 查询当前登录用户拉黑的店铺ID
            List<Integer> blacklistedStoreIds = new ArrayList<>();
            if (userLoginInfo != null && userLoginInfo.getUserId() > 0) {
                // 获取当前登录用户的类型和ID
                String blockerType = userLoginInfo.getType(); // "user" 或 "store"
                String blockerId = String.valueOf(userLoginInfo.getUserId());
                
                // 根据用户类型设置拉黑方类型（1：商户，2：用户）
                String blockerTypeValue = "user".equals(blockerType) ? "2" : "1";
                
                LambdaQueryWrapper<LifeBlacklist> blacklistWrapper = new LambdaQueryWrapper<>();
                blacklistWrapper.eq(LifeBlacklist::getBlockerType, blockerTypeValue) // 拉黑方类型
                               .eq(LifeBlacklist::getBlockerId, blockerId) // 拉黑方ID（当前登录用户）
                               .eq(LifeBlacklist::getBlockedType, "1") // 1表示商户
                               .eq(LifeBlacklist::getDeleteFlag, 0);
                List<LifeBlacklist> blacklist = lifeBlacklistMapper.selectList(blacklistWrapper);
                
                if (!CollectionUtils.isEmpty(blacklist)) {
                    for (LifeBlacklist item : blacklist) {
                        try {
                            if (item.getBlockedId() != null && !item.getBlockedId().trim().isEmpty()) {
                                blacklistedStoreIds.add(Integer.parseInt(item.getBlockedId()));
                            }
                        } catch (NumberFormatException e) {
                            log.warn("拉黑记录中的店铺ID格式错误: {}", item.getBlockedId());
                        }
                    }
                }
            }
            
            // 查询当前登录用户已关注的店铺ID（仅普通用户）
            List<Integer> followedStoreIds = new ArrayList<>();
            if (userLoginInfo != null && userLoginInfo.getUserId() > 0 && "user".equals(userLoginInfo.getType())) {
                try {
                    // 查询用户信息获取手机号
                    Integer userId = userLoginInfo.getUserId();
                    LifeUser lifeUser = lifeUserMapper.selectById(userId);
                    
                    if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                        // 构造粉丝ID：fans_id = "user_" + 用户手机号
                        String fansId = "user_" + lifeUser.getUserPhone();
                        
                        // 查询该用户关注的所有门店（followed_id 以 "store_" 开头）
                        LifeFansIdentityQuery.Scope userScope = LifeFansIdentityQuery.resolve(fansId, typeUtil);
                        LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
                        fansWrapper.eq(LifeFans::getDeleteFlag, 0);
                        LifeFansIdentityQuery.applyFansSide(fansWrapper, userScope);
                        fansWrapper.eq(LifeFans::getFollowedUserType, 2);
                        List<LifeFans> lifeFansList = lifeFansMapper.selectList(fansWrapper);
                        
                        if (!CollectionUtils.isEmpty(lifeFansList)) {
                            // 从 followed_id 中提取门店手机号（去掉 "store_" 前缀）
                            Set<String> storePhones = new HashSet<>();
                            for (LifeFans fans : lifeFansList) {
                                if (fans.getFollowedId() != null && fans.getFollowedId().startsWith("store_")) {
                                    String storePhone = fans.getFollowedId().substring(6); // 去掉 "store_" 前缀
                                    if (StringUtils.isNotEmpty(storePhone)) {
                                        storePhones.add(storePhone);
                                    }
                                }
                            }
                            
                            // 通过门店手机号查询门店ID
                            if (!storePhones.isEmpty()) {
                                LambdaQueryWrapper<StoreInfo> storeWrapper = new LambdaQueryWrapper<>();
                                storeWrapper.in(StoreInfo::getStoreTel, storePhones)
                                          .eq(StoreInfo::getDeleteFlag, 0);
                                List<StoreInfo> followedStores = storeInfoMapper.selectList(storeWrapper);
                                
                                for (StoreInfo store : followedStores) {
                                    if (store.getId() != null) {
                                        followedStoreIds.add(store.getId());
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("查询用户已关注门店失败 - userId: {}, error: {}", 
                            userLoginInfo.getUserId(), e.getMessage(), e);
                }
            }
            
            // 合并拉黑和已关注的店铺ID列表
            Set<Integer> excludedStoreIds = new HashSet<>(blacklistedStoreIds);
            excludedStoreIds.addAll(followedStoreIds);
            
            // 查询所有有头图的店铺ID（img_type 为 20 或 21）
            Set<Integer> storesWithHeadImg = new HashSet<>();
            try {
                LambdaQueryWrapper<StoreImg> headImgWrapper = new LambdaQueryWrapper<>();
                headImgWrapper.in(StoreImg::getImgType, Arrays.asList(20, 21)) // 20:头图单图模式, 21:头图多图模式
                             .eq(StoreImg::getDeleteFlag, 0);
                List<StoreImg> headImgList = storeImgMapper.selectList(headImgWrapper);
                
                if (!CollectionUtils.isEmpty(headImgList)) {
                    for (StoreImg storeImg : headImgList) {
                        if (storeImg.getStoreId() != null) {
                            storesWithHeadImg.add(storeImg.getStoreId());
                        }
                    }
                }
                log.info("查询到有头图的店铺数量: {}", storesWithHeadImg.size());
            } catch (Exception e) {
                log.error("查询有头图的店铺失败 - error: {}", e.getMessage(), e);
                // 如果查询失败，返回空结果
                return R.data(new Page<>(pageNum, pageSize, 0));
            }
            
            // 如果没有有头图的店铺，直接返回空结果
            if (storesWithHeadImg.isEmpty()) {
                log.info("没有找到有头图的店铺");
                return R.data(new Page<>(pageNum, pageSize, 0));
            }
            
            // 构建查询条件
            LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StoreInfo::getDeleteFlag, 0); // 未删除
            
            // 只查询有头图的店铺
            queryWrapper.in(StoreInfo::getId, storesWithHeadImg);
            
            // 排除被拉黑和已关注的店铺
            if (!excludedStoreIds.isEmpty()) {
                queryWrapper.notIn(StoreInfo::getId, excludedStoreIds);
            }
            
            // 随机排序
            queryWrapper.last("ORDER BY RAND()");
            
            // 构建分页对象
            IPage<StoreInfo> pageObj = new Page<>(pageNum, pageSize);
            
            // 执行分页查询
            IPage<StoreInfo> result = storeInfoMapper.selectPage(pageObj, queryWrapper);
            
            // 批量查询商户头像和手机号
            List<Integer> storeIds = new ArrayList<>();
            for (StoreInfo store : result.getRecords()) {
                if (store.getId() != null) {
                    storeIds.add(store.getId());
                }
            }
            
            Map<Integer, String> headImgMap = new HashMap<>();
            Map<Integer, String> storePhoneMap = new HashMap<>(); // 店铺ID -> 门店手机号
            if (!storeIds.isEmpty()) {
                // 批量查询店铺信息，获取门店手机号
                List<StoreInfo> storeInfoList = storeInfoMapper.selectBatchIds(storeIds);
                for (StoreInfo storeInfo : storeInfoList) {
                    if (storeInfo.getId() != null && StringUtils.isNotEmpty(storeInfo.getStoreTel())) {
                        storePhoneMap.put(storeInfo.getId(), storeInfo.getStoreTel());
                    }
                }
                
                LambdaQueryWrapper<StoreUser> userWrapper = new LambdaQueryWrapper<>();
                userWrapper.in(StoreUser::getStoreId, storeIds)
                          .eq(StoreUser::getDeleteFlag, 0);
                List<StoreUser> storeUsers = storeUserMapper.selectList(userWrapper);
                for (StoreUser user : storeUsers) {
                    if (user.getStoreId() != null) {
                        // 如果同一个店铺有多个用户，取第一个（通常是主账号）
                        if (user.getHeadImg() != null) {
                            headImgMap.putIfAbsent(user.getStoreId(), user.getHeadImg());
                        }
                    }
                }
            }
            
            // 转换为包含头像和关注状态的VO对象
            List<StoreInfoWithHeadImg> voList = new ArrayList<>();
            for (StoreInfo store : result.getRecords()) {
                StoreInfoWithHeadImg vo = new StoreInfoWithHeadImg();
                BeanUtils.copyProperties(store, vo);
                // 获取商户头像，如果没有头像则设置为null
                String headImg = headImgMap.get(store.getId());
                vo.setHeadImg(headImg != null && !headImg.trim().isEmpty() ? headImg : null);
                
                // 当前登录用户是否关注该店铺
                Integer isFollowed = 0; // 默认未关注
                if (userLoginInfo != null && userLoginInfo.getUserId() > 0 && "user".equals(userLoginInfo.getType())) {
                    try {
                        // userId是用户ID（数字），查询用户信息获取手机号
                        Integer userId = userLoginInfo.getUserId();
                        LifeUser lifeUser = lifeUserMapper.selectById(userId);

                        // 获取门店手机号
                        String storePhone = storePhoneMap.get(store.getId());

                        if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())
                                && StringUtils.isNotEmpty(storePhone)) {
                            // 构造关注关系：followed_id = "store_" + 门店手机号，fans_id = "user_" + 用户手机号
                            String followedId = "store_" + storePhone;
                            String fansId = "user_" + lifeUser.getUserPhone();

                            // 查询关注关系
                            LifeFansIdentityQuery.Scope fanScope = LifeFansIdentityQuery.resolve(fansId, typeUtil);
                            LifeFansIdentityQuery.Scope followedScope = LifeFansIdentityQuery.resolve(followedId, typeUtil);
                            LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
                            LifeFansIdentityQuery.applyPairWithDeleteFlag(fansWrapper, fanScope, followedScope);
                            LifeFans lifeFans = lifeFansMapper.selectOne(fansWrapper);

                            if (lifeFans != null) {
                                isFollowed = 1; // 已关注
                            } else {
                                isFollowed = 0; // 未关注
                            }
                        } else {
                            isFollowed = 0; // 无法获取用户手机号或店铺手机号，默认未关注
                        }
                    } catch (NumberFormatException e) {
                        log.error("用户ID格式错误 - userId: {}, storeId: {}, error: {}",
                                userLoginInfo.getUserId(), store.getId(), e.getMessage());
                        isFollowed = 0; // 用户ID格式错误，默认未关注
                    } catch (Exception e) {
                        log.error("查询用户关注状态失败 - userId: {}, storeId: {}, error: {}",
                                userLoginInfo.getUserId(), store.getId(), e.getMessage(), e);
                        isFollowed = 0; // 查询失败，默认未关注
                    }
                } else {
                    isFollowed = 0; // 用户未登录或不是普通用户，默认未关注
                }
                
                vo.setIsFollowed(isFollowed);
                voList.add(vo);
            }
            
            // 构建返回结果
            IPage<StoreInfoWithHeadImg> voPage = new Page<>(pageNum, pageSize, result.getTotal());
            voPage.setRecords(voList);
            
            log.info("分页随机查询店铺成功 - 共{}条记录，当前页{}条", voPage.getTotal(), voList.size());
            return R.data(voPage);
        } catch (Exception e) {
            log.error("分页随机查询店铺失败 - page={}, size={}, error={}", page, size, e.getMessage(), e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据经营板块返回店铺详情页可展示的标签（仅当对应接口有数据时才展示）
     * <p>
     * 美食：价目表、人员；
     * 休闲娱乐：价目表、人员、演出；
     * 生活服务：价目表、设施、教练、人员。
     * 每个标签会调用对应数据接口判断是否有数据，无数据则不返回该标签。
     * </p>
     *
     * @param storeId         门店 ID
     * @param businessSection 经营板块：传 dictId 或名称。1/美食、2/休闲娱乐、3/生活服务
     * @return 有数据的标签列表，每项包含标签名和对应接口路径
     */
    @ApiOperation("根据经营板块获取店铺详情页展示标签（仅展示有数据的标签）")
    @ApiOperationSupport(order = 100)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "businessSection", value = "经营板块：1或美食、2或休闲娱乐、3或生活服务", dataType = "String", paramType = "query", required = true)
    })
    @GetMapping("/getStoreSectionTags")
    public R<Map<String, Boolean>> getStoreSectionTags(
            @RequestParam Integer storeId,
            @RequestParam String businessSection) {
        log.info("StoreInfoController.getStoreSectionTags?storeId={}, businessSection={}", storeId, businessSection);
        if (storeId == null) {
            return R.fail("门店ID不能为空");
        }
        if (StringUtils.isBlank(businessSection)) {
            return R.fail("经营板块不能为空");
        }
        String section = businessSection.trim();
        boolean isFood = "3".equals(section) || "美食".equals(section);
        boolean isLeisure = "1".equals(section) || "休闲娱乐".equals(section);
        boolean isLifeService = "2".equals(section) || "生活服务".equals(section);
        if (!isFood && !isLeisure && !isLifeService) {
            return R.fail("未知的经营板块: " + businessSection);
        }
        Map<String, Boolean> tags = buildSectionTagsByData(storeId, isFood, isLeisure, isLifeService);
        return R.data(tags);
    }

    /**
     * 根据实际数据判断各标签是否有数据，返回 Map（key 为标签名，value 有数据 true / 无数据 false）
     */
    private Map<String, Boolean> buildSectionTagsByData(Integer storeId, boolean isFood, boolean isLeisure, boolean isLifeService) {
        Map<String, Boolean> map = new HashMap<>(8);

        map.put("showPriceCard", hasPriceListData(storeId));
        map.put("showStaffCard", hasStaffData(storeId));
        map.put("showPerformance", hasPerformanceData(storeId));
        // yan chu quan yao,zuo you nao hu bo,wu di le ☺.
/*        if (isLeisure || isFood) {
            map.put("showPerformance", hasPerformanceData(storeId));
        }*/
        if (isLifeService) {
            map.put("showFacilityServiceCard", hasFacilityData(storeId));
        }

        return map;
    }

    /** 价目表是否有数据：美食价目或通用价目存在且已上架 */
    private boolean hasPriceListData(Integer storeId) {
        long cuisineCount = storeCuisineService.count(
                new LambdaQueryWrapper<StoreCuisine>()
                        .eq(StoreCuisine::getStoreId, storeId)
                        .eq(StoreCuisine::getShelfStatus, 1));
        if (cuisineCount > 0) {
            return true;
        }
        return storePriceService.count(
                new LambdaQueryWrapper<StorePrice>()
                        .eq(StorePrice::getStoreId, storeId)
                        .eq(StorePrice::getShelfStatus, 1)) > 0;
    }

    /** 人员是否有数据：按标题分组的员工列表非空 */
    private boolean hasStaffData(Integer storeId) {
        try {
            List<StaffTitleGroupVo> groups = storeStaffConfigService.queryStaffListByTitle(storeId);
            if (CollectionUtils.isEmpty(groups)) {
                return false;
            }
            for (StaffTitleGroupVo group : groups) {
                if (group != null && CollectionUtils.isNotEmpty(group.getStaffList())) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            log.warn("查询人员数据异常 storeId={}, {}", storeId, e.getMessage());
            return false;
        }
    }

    /** 演出是否有数据：演出列表接口有记录 */
    private boolean hasPerformanceData(Integer storeId) {
        try {
            IPage<PerformanceListVo> page = performanceListService.queryPerformanceList(1, 1, storeId);
            return page != null && page.getTotal() > 0;
        } catch (Exception e) {
            log.warn("查询演出数据异常 storeId={}, {}", storeId, e.getMessage());
            return false;
        }
    }

    /** 设施是否有数据：运动器材设施分类汇总有数据 */
    private boolean hasFacilityData(Integer storeId) {
        try {
            List<SportsEquipmentFacilityCategorySummaryVo> list = sportsEquipmentFacilityService.getCategorySummary(storeId);
            return CollectionUtils.isNotEmpty(list);
        } catch (Exception e) {
            log.warn("查询设施数据异常 storeId={}, {}", storeId, e.getMessage());
            return false;
        }
    }


    /**
     * 店铺信息（包含商户头像）
     */
    @Data
    @EqualsAndHashCode(callSuper = true)
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @ApiModel(value = "StoreInfoWithHeadImg对象", description = "店铺信息（包含商户头像）")
    public static class StoreInfoWithHeadImg extends StoreInfo {
        @ApiModelProperty(value = "商户头像（来自store_user表的head_img字段）")
        @TableField(exist = false)
        private String headImg;
        
        @ApiModelProperty(value = "是否已关注（1-已关注，0-未关注）")
        @TableField(exist = false)
        private Integer isFollowed;
    }


}
