/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

// 该类所属的包名，表明其位于管理端控制器相关的包下，用于对店铺详情相关操作进行控制和处理
package com.yami.shop.admin.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.param.ShopDetailParam;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.ShopDetailService;
import cn.hutool.core.bean.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import com.yami.shop.common.response.ServerResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ShopDetailController类是一个Spring RESTful风格的控制器，用于处理与店铺详情（ShopDetail）相关的各种后台管理操作接口。
 * 涵盖了诸如修改分销开关、获取店铺详情信息、分页查询店铺详情、保存店铺详情、修改店铺详情、删除店铺详情、更新店铺状态以及获取所有店铺名称等功能。
 *
 * @author lgh on 2018/08/29.
 */
@RestController
// 定义该控制器类的基础请求路径，所有该类中的接口请求路径都将以此为前缀，表明是与店铺详情相关的操作接口
@RequestMapping("/shop/shopDetail")
public class ShopDetailController {

    // 通过Spring的依赖注入机制，自动注入ShopDetailService的实例，以便调用其提供的与店铺详情相关的业务逻辑方法
    @Autowired
    private ShopDetailService shopDetailService;

    /**
     * 修改分销开关的接口方法。
     * 根据传入的分销开关状态参数（isDistribution），创建一个ShopDetail对象，设置店铺ID（通过SecurityUtils获取当前系统用户的店铺ID）以及分销开关状态，
     * 然后调用ShopDetailService的updateById方法更新数据库中对应店铺的分销开关状态，更新完成后调用removeShopDetailCacheByShopId方法删除对应店铺ID的缓存，
     * 最后返回表示操作成功的ServerResponseEntity对象，用于统一的接口响应格式处理，其无具体数据内容（Void类型）。
     *
     * @param isDistribution 表示分销开关状态的整数参数，通常可能是0或1等表示关闭或开启的状态值。
     * @return 返回表示操作成功的ServerResponseEntity，无数据内容（Void类型）。
     */
    @PutMapping("/isDistribution")
    public ServerResponseEntity<Void> updateIsDistribution(@RequestParam Integer isDistribution) {
        ShopDetail shopDetail = new ShopDetail();
        shopDetail.setShopId(SecurityUtils.getSysUser().getShopId());
        shopDetail.setIsDistribution(isDistribution);
        shopDetailService.updateById(shopDetail);
        // 更新完成后删除缓存
        shopDetailService.removeShopDetailCacheByShopId(shopDetail.getShopId());
        return ServerResponseEntity.success();
    }

    /**
     * 获取当前用户所属店铺详情信息的接口方法。
     * 通过SecurityUtils获取当前系统用户的店铺ID，调用ShopDetailService的getShopDetailByShopId方法获取对应的店铺详情对象，
     * 再将获取到的店铺详情对象封装在ServerResponseEntity中返回，用于统一的接口响应格式处理。
     *
     * @return 返回包含当前用户所属店铺详情信息的ServerResponseEntity，成功时其数据部分为ShopDetail类型。
     */
    @GetMapping("/info")
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:info')")
    public ServerResponseEntity<ShopDetail> info() {
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(SecurityUtils.getSysUser().getShopId());
        return ServerResponseEntity.success(shopDetail);
    }

    /**
     * 分页获取店铺详情信息的接口方法。
     * 根据传入的ShopDetail对象（可能包含店铺名称等查询条件）以及PageParam对象（用于分页参数设置），
     * 使用ShopDetailService的page方法结合LambdaQueryWrapper进行分页查询。如果店铺名称不为空，则按照店铺名称进行模糊查询，
     * 并且按照店铺ID降序排序，最后将查询到的分页店铺详情数据封装在ServerResponseEntity中返回，用于统一的接口响应格式处理。
     *
     * @param shopDetail 可能包含查询条件的店铺详情对象，比如按店铺名称模糊查询。
     * @param page 分页参数对象，包含页码、每页数量等信息。
     * @return 返回包含分页店铺详情信息的ServerResponseEntity，成功时其数据部分为IPage<ShopDetail>类型。
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:page')")
    public ServerResponseEntity<IPage<ShopDetail>> page(ShopDetail shopDetail, PageParam<ShopDetail> page) {
        IPage<ShopDetail> shopDetails = shopDetailService.page(page,
                new LambdaQueryWrapper<ShopDetail>()
                     .like(StrUtil.isNotBlank(shopDetail.getShopName()), ShopDetail::getShopName, shopDetail.getShopName())
                     .orderByDesc(ShopDetail::getShopId));
        return ServerResponseEntity.success(shopDetails);
    }

    /**
     * 根据店铺ID获取店铺详情信息的接口方法。
     * 通过路径变量获取要查询的店铺的ID，调用ShopDetailService的getShopDetailByShopId方法获取对应的店铺详情对象，
     * 再将获取到的店铺详情对象封装在ServerResponseEntity中返回，用于统一的接口响应格式处理。
     *
     * @param shopId 要获取信息的店铺的唯一标识符（ID）。
     * @return 返回包含指定店铺详情信息的ServerResponseEntity，成功时其数据部分为ShopDetail类型。
     */
    @GetMapping("/info/{shopId}")
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:info')")
    public ServerResponseEntity<ShopDetail> info(@PathVariable("shopId") Long shopId) {
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        // 店铺图片（此处可根据实际业务需求进一步处理店铺图片相关逻辑，目前只是简单返回店铺详情对象）
        return ServerResponseEntity.success(shopDetail);
    }

    /**
     * 保存店铺详情信息的接口方法。
     * 首先将传入的ShopDetailParam对象（可能包含部分店铺详情信息）通过BeanUtil复制属性到ShopDetail对象中，
     * 然后设置创建时间为当前时间（通过new Date()获取）以及店铺状态为默认值（这里设置为1，具体含义需根据业务定义），
     * 最后调用ShopDetailService的save方法将店铺详情信息保存到数据库中，返回表示保存成功的ServerResponseEntity对象，用于统一的接口响应格式处理，其无具体数据内容（Void类型）。
     *
     * @param shopDetailParam 包含店铺详情部分信息的参数对象，用于传入要保存的店铺相关属性。
     * @return 返回表示保存成功的ServerResponseEntity，无数据内容（Void类型）。
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:save')")
    public ServerResponseEntity<Void> save(@Valid ShopDetailParam shopDetailParam) {
        ShopDetail shopDetail = BeanUtil.copyProperties(shopDetailParam, ShopDetail.class);
        shopDetail.setCreateTime(new Date());
        shopDetail.setShopStatus(1);
        shopDetailService.save(shopDetail);
        return ServerResponseEntity.success();
    }

    /**
     * 修改店铺详情信息的接口方法。
     * 先调用ShopDetailService的getShopDetailByShopId方法根据传入的ShopDetailParam中的店铺ID获取数据库中已存在的店铺详情对象（daShopDetail），
     * 再将ShopDetailParam对象通过BeanUtil复制属性到ShopDetail对象中，并设置更新时间为当前时间（通过new Date()获取），
     * 然后调用ShopDetailService的updateShopDetail方法（可能包含自定义的更新逻辑，比如判断哪些字段需要更新等）更新店铺详情信息，
     * 最后返回表示修改成功的ServerResponseEntity对象，用于统一的接口响应格式处理，其无具体数据内容（Void类型）。
     *
     * @param shopDetailParam 包含要修改的店铺详情部分信息的参数对象，用于传入修改后的店铺相关属性。
     * @return 返回表示修改成功的ServerResponseEntity，无数据内容（Void类型）。
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:update')")
    public ServerResponseEntity<Void> update(@Valid ShopDetailParam shopDetailParam) {
        ShopDetail daShopDetail = shopDetailService.getShopDetailByShopId(shopDetailParam.getShopId());
        ShopDetail shopDetail = BeanUtil.copyProperties(shopDetailParam, ShopDetail.class);
        shopDetail.setUpdateTime(new Date());
        shopDetailService.updateShopDetail(shopDetail, daShopDetail);
        return ServerResponseEntity.success();
    }

    /**
     * 根据店铺ID删除店铺详情信息的接口方法。
     * 通过路径变量获取要删除的店铺的ID，调用ShopDetailService的deleteShopDetailByShopId方法删除数据库中对应的店铺详情记录，
     * 最后返回表示操作成功的ServerResponseEntity对象，用于统一的接口响应格式处理，其无具体数据内容（Void类型）。
     *
     * @param id 要删除的店铺的唯一标识符（ID）。
     * @return 返回表示操作成功的ServerResponseEntity，无数据内容（Void类型）。
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:delete')")
    public ServerResponseEntity<Void> delete(@PathVariable Long id) {
        shopDetailService.deleteShopDetailByShopId(id);
        return ServerResponseEntity.success();
    }

    /**
     * 更新店铺状态的接口方法。
     * 根据传入的店铺ID（shopId）和店铺状态（shopStatus）参数，创建一个ShopDetail对象，设置对应的店铺ID和店铺状态，
     * 然后调用ShopDetailService的updateById方法更新数据库中对应店铺的状态，更新完成后调用removeShopDetailCacheByShopId方法删除对应店铺ID的缓存，
     * 最后返回表示操作成功的ServerResponseEntity对象，用于统一的接口响应格式处理，其无具体数据内容（Void类型）。
     *
     * @param shopId 要更新状态的店铺的唯一标识符（ID）。
     * @param shopStatus 表示店铺新状态的整数参数，具体取值含义需根据业务定义。
     * @return 返回表示操作成功的ServerResponseEntity，无数据内容（Void类型）。
     */
    @PutMapping("/shopStatus")
    @PreAuthorize("@pms.hasPermission('shop:shopDetail:shopStatus')")
    public ServerResponseEntity<Void> shopStatus(@RequestParam Long shopId, @RequestParam Integer shopStatus) {
        ShopDetail shopDetail = new ShopDetail();
        shopDetail.setShopId(shopId);
        shopDetail.setShopStatus(shopStatus);
        shopDetailService.updateById(shopDetail);
        // 更新完成后删除缓存
        shopDetailService.removeShopDetailCacheByShopId(shopDetail.getShopId());
        return ServerResponseEntity.success();
    }

    /**
     * 获取所有店铺名称的接口方法。
     * 首先调用ShopDetailService的list方法获取所有的店铺详情列表，然后通过Java 8的Stream流操作，
     * 将每个店铺详情对象中的店铺ID和店铺名称提取出来，封装到新的ShopDetail对象中，组成一个新的列表，
     * 最后将这个包含店铺名称信息的列表封装在ServerResponseEntity中返回，用于统一的接口响应格式处理。
     *
     * @return 返回包含所有店铺名称信息的ServerResponseEntity，成功时其数据部分为List<ShopDetail>类型，这里的ShopDetail对象仅包含店铺ID和店铺名称属性。
     */
    @GetMapping("/listShopName")
    public ServerResponseEntity<List<ShopDetail>> listShopName() {
        List<ShopDetail> list = shopDetailService.list().stream().map((dbShopDetail) -> {
            ShopDetail shopDetail = new ShopDetail();
            shopDetail.setShopId(dbShopDetail.getShopId());
            shopDetail.setShopName(dbShopDetail.getShopName());
            return shopDetail;
        }).collect(Collectors.toList());
        return ServerResponseEntity.success(list);
    }
}