/*
 * 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.Brand;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.service.BrandService;
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.Objects;

/**
 * 品牌管理
 * 该类主要用于处理品牌相关的后台管理操作接口，包含品牌信息的分页查询、获取单个品牌信息、品牌的保存、修改以及删除等功能。
 * @author lgh
 */
@RestController
@RequestMapping("/admin/brand")
public class BrandController {

    // 自动注入BrandService，用于调用与品牌相关的业务逻辑方法
    @Autowired
    private BrandService brandService;

    /**
     * 分页获取品牌信息的接口方法
     * 通过接收Brand对象（可能包含品牌名称等查询条件）以及PageParam对象（用于分页参数设置），
     * 利用BrandService的page方法结合LambdaQueryWrapper进行分页查询，查询条件中如果品牌名称不为空则进行模糊匹配，
     * 并且按照品牌名称首字符升序排序，最后返回包含查询结果的ServerResponseEntity对象。
     * @param brand 可能包含查询条件的品牌对象，比如按品牌名称模糊查询
     * @param page 分页参数对象，包含页码、每页数量等信息
     * @return 返回包含分页品牌信息的ServerResponseEntity，成功时其数据部分为IPage<Brand>类型
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('admin:brand:page')")
    public ServerResponseEntity<IPage<Brand>> page(Brand brand, PageParam<Brand> page) {
        IPage<Brand> brands = brandService.page(page,
                new LambdaQueryWrapper<Brand>()
                      .like(StrUtil.isNotBlank(brand.getBrandName()), Brand::getBrandName, brand.getBrandName())
                      .orderByAsc(Brand::getFirstChar));
        return ServerResponseEntity.success(brands);
    }

    /**
     * 获取指定ID品牌详细信息的接口方法
     * 通过路径变量获取品牌的ID，调用BrandService的getById方法获取对应的品牌对象，
     * 最后返回包含该品牌对象信息的ServerResponseEntity对象。
     * @param id 要获取信息的品牌的ID
     * @return 返回包含指定品牌详细信息的ServerResponseEntity，成功时其数据部分为Brand类型
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("@pms.hasPermission('admin:brand:info')")
    public ServerResponseEntity<Brand> info(@PathVariable("id") Long id) {
        Brand brand = brandService.getById(id);
        return ServerResponseEntity.success(brand);
    }

    /**
     * 保存品牌信息的接口方法
     * 首先调用BrandService的getByBrandName方法，根据传入品牌对象的名称查询数据库中是否已存在同名品牌，
     * 如果存在则抛出异常（表示品牌名称已存在），若不存在则调用BrandService的save方法保存品牌信息，
     * 最后返回表示成功的ServerResponseEntity对象。
     * @param brand 要保存的品牌对象，通过请求体传入，且经过了数据校验（@Valid注解）
     * @return 返回表示保存成功的ServerResponseEntity，无数据内容（Void类型）
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('admin:brand:save')")
    public ServerResponseEntity<Void> save(@Valid Brand brand) {
        Brand dbBrand = brandService.getByBrandName(brand.getBrandName());
        if (dbBrand!= null) {
            throw new YamiShopBindException("该品牌名称已存在");
        }
        brandService.save(brand);
        return ServerResponseEntity.success();
    }

    /**
     * 修改品牌信息的接口方法
     * 先调用BrandService的getByBrandName方法，根据传入品牌对象的名称查询数据库中是否已存在同名品牌（除了自身），
     * 如果存在同名且ID不同的品牌则抛出异常（表示品牌名称已存在且冲突），若不存在冲突则调用BrandService的updateById方法更新品牌信息，
     * 最后返回表示成功的ServerResponseEntity对象。
     * @param brand 要修改的品牌对象，通过请求体传入，且经过了数据校验（@Valid注解）
     * @return 返回表示修改成功的ServerResponseEntity，无数据内容（Void类型）
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('admin:brand:update')")
    public ServerResponseEntity<Void> update(@Valid Brand brand) {
        Brand dbBrand = brandService.getByBrandName(brand.getBrandName());
        if (dbBrand!= null &&!Objects.equals(dbBrand.getBrandId(), brand.getBrandId())) {
            throw new YamiShopBindException("该品牌名称已存在");
        }
        brandService.updateById(brand);
        return ServerResponseEntity.success();
    }

    /**
     * 删除品牌信息的接口方法
     * 根据路径变量获取要删除品牌的ID，调用BrandService的deleteByBrand方法删除对应品牌信息，
     * 最后返回表示成功的ServerResponseEntity对象。
     * @param id 要删除的品牌的ID
     * @return 返回表示删除成功的ServerResponseEntity，无数据内容（Void类型）
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("@pms.hasPermission('admin:brand:delete')")
    public ServerResponseEntity<Void> delete(@PathVariable Long id) {
        brandService.deleteByBrand(id);
        return ServerResponseEntity.success();
    }
}