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

package com.yami.shop.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.IndexImg;
import com.yami.shop.bean.model.Product;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.IndexImgService;
import com.yami.shop.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import com.yami.shop.common.response.ServerResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.Date;
import java.util.Objects;

/**
 * 首页图片（IndexImg）相关的控制器类，主要负责处理首页图片的增删改查操作，
 * 包括分页查询、获取单条信息、保存、修改和删除等功能，并且在各个操作方法上添加了相应的权限控制，
 * 同时在部分操作中涉及与商品信息的关联校验等业务逻辑。
 *
 * @author lgh on 2018/11/26.
 */
@RestController
@RequestMapping("/admin/indexImg")
public class IndexImgController {

    // 注入IndexImgService，用于处理与首页图片相关的业务逻辑，例如图片信息的查询、保存、更新、删除等操作。
    @Autowired
    private IndexImgService indexImgService;

    // 注入ProductService，用于获取商品相关信息，在涉及首页图片与商品关联的业务逻辑中会用到，比如校验商品状态等情况。
    @Autowired
    private ProductService productService;

    /**
     * 分页获取首页图片信息的方法，根据传入的查询条件（IndexImg对象）和分页参数（PageParam对象），
     * 通过IndexImgService进行分页查询，同时可以根据图片状态进行筛选，并按照顺序排序，最后将查询到的分页结果返回给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"admin:indexImg:page"权限的用户才能访问此方法。
     *
     * @param indexImg 包含查询条件的IndexImg对象，例如可以设置图片状态等筛选条件。
     * @param page 分页参数对象，用于指定页码、每页数量等分页相关信息。
     * @return 返回包含分页后的首页图片信息的ServerResponseEntity对象，若查询成功则响应体中包含符合条件的分页图片数据，否则返回相应错误信息。
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('admin:indexImg:page')")
    public ServerResponseEntity<IPage<IndexImg>> page(IndexImg indexImg, PageParam<IndexImg> page) {
        // 使用IndexImgService的page方法进行分页查询，传入分页参数和LambdaQueryWrapper构建的查询条件，
        // 根据传入的indexImg对象的状态是否不为空来决定是否添加状态筛选条件，同时按照顺序排序。
        IPage<IndexImg> indexImgPage = indexImgService.page(page,
                new LambdaQueryWrapper<IndexImg>()
                      .eq(indexImg.getStatus()!= null, IndexImg::getStatus, indexImg.getStatus())
                      .orderByAsc(IndexImg::getSeq));
        return ServerResponseEntity.success(indexImgPage);
    }

    /**
     * 根据图片ID获取首页图片详细信息的方法，先根据当前登录用户所属的店铺ID以及传入的图片ID，
     * 通过IndexImgService查询对应的首页图片信息，若图片存在关联商品，则进一步获取商品信息并设置到图片对象中相关属性（如商品图片、商品名称等），
     * 最后将包含详细信息的图片对象封装在成功的响应实体中返回给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"admin:indexImg:info"权限的用户才能访问此方法。
     *
     * @param imgId 要获取详细信息的首页图片的唯一标识符。
     * @return 返回包含首页图片详细信息的ServerResponseEntity对象，若获取成功则响应体中包含对应的图片对象及关联商品信息（若有），否则返回相应错误信息。
     */
    @GetMapping("/info/{imgId}")
    @PreAuthorize("@pms.hasPermission('admin:indexImg:info')")
    public ServerResponseEntity<IndexImg> info(@PathVariable("imgId") Long imgId) {
        Long shopId = SecurityUtils.getSysUser().getShopId();
        // 通过IndexImgService根据店铺ID和图片ID查询对应的首页图片对象，使用LambdaQueryWrapper构建查询条件。
        IndexImg indexImg = indexImgService.getOne(new LambdaQueryWrapper<IndexImg>().eq(IndexImg::getShopId, shopId).eq(IndexImg::getImgId, imgId));
        if (Objects.nonNull(indexImg.getRelation())) {
            // 若图片存在关联商品（通过relation属性判断），则通过ProductService根据商品ID获取商品对象。
            Product product = productService.getProductByProdId(indexImg.getRelation());
            // 将商品的图片和商品名称设置到首页图片对象的相应属性中，方便前端展示关联商品的相关信息。
            indexImg.setPic(product.getPic());
            indexImg.setProdName(product.getProdName());
        }
        return ServerResponseEntity.success(indexImg);
    }

    /**
     * 保存首页图片信息的方法，接收一个经过验证（通过@Valid注解）的IndexImg对象作为请求体，代表要保存的图片信息。
     * 首先设置图片所属的店铺ID（通过当前登录用户所属店铺ID确定）以及上传时间等信息，然后调用私有方法checkProdStatus对图片关联的商品状态进行校验，
     * 若校验通过则调用IndexImgService的save方法将图片信息保存到数据库中，并清除首页图片缓存（可能用于更新缓存数据，确保数据一致性），
     * 最后返回成功的响应结果给前端。通过@PreAuthorize注解进行权限控制，只有具备"admin:indexImg:save"权限的用户才能访问此方法。
     *
     * @param indexImg 包含要保存的首页图片信息的请求体对象，如图片名称、关联商品、状态等属性。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行保存操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('admin:indexImg:save')")
    public ServerResponseEntity<Void> save(@RequestBody @Valid IndexImg indexImg) {
        Long shopId = SecurityUtils.getSysUser().getShopId();
        indexImg.setShopId(shopId);
        indexImg.setUploadTime(new Date());
        checkProdStatus(indexImg);
        indexImgService.save(indexImg);
        indexImgService.removeIndexImgCache();
        return ServerResponseEntity.success();
    }

    /**
     * 修改首页图片信息的方法，接收一个经过验证（通过@Valid注解）的IndexImg对象作为请求体，代表要更新的图片信息。
     * 首先调用私有方法checkProdStatus对图片关联的商品状态进行校验，若校验通过则调用IndexImgService的saveOrUpdate方法将更新后的图片信息保存到数据库中，
     * 并清除首页图片缓存（可能用于更新缓存数据，确保数据一致性），最后返回成功的响应结果给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"admin:indexImg:update"权限的用户才能访问此方法。
     *
     * @param indexImg 包含要更新的首页图片信息的请求体对象，如图片名称、关联商品、状态等属性。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行更新操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('admin:indexImg:update')")
    public ServerResponseEntity<Void> update(@RequestBody @Valid IndexImg indexImg) {
        checkProdStatus(indexImg);
        indexImgService.saveOrUpdate(indexImg);
        indexImgService.removeIndexImgCache();
        return ServerResponseEntity.success();
    }

    /**
     * 删除首页图片信息的方法，接收一个包含要删除的图片ID数组的请求体，通过IndexImgService的deleteIndexImgByIds方法，
     * 根据传入的图片ID数组批量删除对应的首页图片信息，并清除首页图片缓存（可能用于更新缓存数据，确保数据一致性），
     * 最后返回成功的响应结果给前端。通过@PreAuthorize注解进行权限控制，只有具备"admin:indexImg:delete"权限的用户才能访问此方法。
     *
     * @param ids 包含要删除的首页图片ID的数组。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行删除操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('admin:indexImg:delete')")
    public ServerResponseEntity<Void> delete(@RequestBody Long[] ids) {
        indexImgService.deleteIndexImgByIds(ids);
        indexImgService.removeIndexImgCache();
        return ServerResponseEntity.success();
    }

    /**
     * 私有方法，用于校验首页图片关联的商品状态是否符合要求，若图片类型不是特定类型（这里假设类型0表示与商品关联的情况）则直接返回，
     * 若关联商品ID为空则抛出异常提示请选择商品，若根据商品ID查询不到商品信息则抛出异常提示商品信息不存在，
     * 若商品状态不是上架状态（这里假设状态1表示上架）则抛出异常提示该商品未上架，请选择别的商品。
     *
     * @param indexImg 包含首页图片信息的对象，用于获取关联商品ID以及图片类型等属性进行校验。
     */
    private void checkProdStatus(IndexImg indexImg) {
        if (!Objects.equals(indexImg.getType(), 0)) {
            return;
        }
        if (Objects.isNull(indexImg.getRelation())) {
            throw new YamiShopBindException("请选择商品");
        }
        Product product = productService.getById(indexImg.getRelation());
        if (Objects.isNull(product)) {
            throw new YamiShopBindException("商品信息不存在");
        }
        if (!Objects.equals(product.getStatus(), 1)) {
            throw new YamiShopBindException("该商品未上架，请选择别的商品");
        }
    }
}