/*
 * 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.PickAddr;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.PickAddrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

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

/**
 * 提货地址（PickAddr）相关的控制器类，主要负责处理提货地址的增删改查操作，
 * 各个方法分别实现了分页查询、获取单个地址信息、保存地址、更新地址以及删除地址等功能，
 * 并且在相应操作上添加了权限控制，确保只有具备对应权限的用户才能执行相应操作。
 *
 * @author lgh on 2018/10/17.
 */
@RestController
@RequestMapping("/shop/pickAddr")
public class PickAddrController {

    // 注入PickAddrService，用于与提货地址相关的业务逻辑处理，例如查询、保存、更新、删除提货地址等操作。
    @Autowired
    private PickAddrService pickAddrService;

    /**
     * 分页获取提货地址信息的方法，根据传入的查询条件（PickAddr对象）和分页参数（PageParam对象），
     * 通过PickAddrService进行分页查询，查询时可根据提货地址名称进行模糊匹配（如果名称不为空），并按照地址ID倒序排序，
     * 最后将查询到的分页结果封装在成功的响应实体中返回给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"shop:pickAddr:page"权限的用户才能访问此方法。
     *
     * @param pickAddr 包含查询条件的PickAddr对象，可设置提货地址名称等筛选条件。
     * @param page 分页参数对象，用于指定页码、每页数量等分页相关信息。
     * @return 返回包含分页后的提货地址信息的ServerResponseEntity对象，若查询成功则响应体中包含符合条件的分页地址数据，否则返回相应错误信息。
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('shop:pickAddr:page')")
    public ServerResponseEntity<IPage<PickAddr>> page(PickAddr pickAddr, PageParam<PickAddr> page) {
        // 使用PickAddrService的page方法进行分页查询，传入分页参数和LambdaQueryWrapper构建的查询条件。
        // 通过StrUtil.isNotBlank判断提货地址名称是否不为空，若不为空则添加模糊查询条件，按照地址名称进行模糊匹配，最后按照地址ID倒序排序。
        IPage<PickAddr> pickAddrs = pickAddrService.page(page, new LambdaQueryWrapper<PickAddr>()
              .like(StrUtil.isNotBlank(pickAddr.getAddrName()), PickAddr::getAddrName, pickAddr.getAddrName())
              .orderByDesc(PickAddr::getAddrId));
        return ServerResponseEntity.success(pickAddrs);
    }

    /**
     * 根据提货地址ID获取提货地址详细信息的方法，通过传入的提货地址ID，调用PickAddrService的getById方法从数据库中查询对应的提货地址对象，
     * 并将其封装在成功的响应实体中返回给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"shop:pickAddr:info"权限的用户才能访问此方法。
     *
     * @param id 要获取详细信息的提货地址的唯一标识符。
     * @return 返回包含提货地址详细信息的ServerResponseEntity对象，若获取成功则响应体中包含对应的提货地址对象，否则返回相应错误信息。
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("@pms.hasPermission('shop:pickAddr:info')")
    public ServerResponseEntity<PickAddr> info(@PathVariable("id") Long id) {
        PickAddr pickAddr = pickAddrService.getById(id);
        return ServerResponseEntity.success(pickAddr);
    }

    /**
     * 保存提货地址信息的方法，接收一个经过验证（通过@Valid注解）的PickAddr对象作为请求体，代表要保存的提货地址信息。
     * 首先设置提货地址所属的店铺ID（通过当前登录用户所属店铺ID确定），然后调用PickAddrService的save方法将提货地址信息保存到数据库中，
     * 最后返回成功的响应结果给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"shop:pickAddr:save"权限的用户才能访问此方法。
     *
     * @param pickAddr 包含要保存的提货地址信息的请求体对象，如地址名称、详细地址等属性。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行保存操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('shop:pickAddr:save')")
    public ServerResponseEntity<Void> save(@Valid @RequestBody PickAddr pickAddr) {
        pickAddr.setShopId(SecurityUtils.getSysUser().getShopId());
        pickAddrService.save(pickAddr);
        return ServerResponseEntity.success();
    }

    /**
     * 修改提货地址信息的方法，接收一个经过验证（通过@Valid注解）的PickAddr对象作为请求体，代表要更新的提货地址信息。
     * 首先通过PickAddrService的getById方法根据传入的提货地址ID从数据库中获取对应的提货地址对象，用于后续权限判断，
     * 判断当前登录用户所属的店铺ID与要修改的提货地址所属的店铺ID是否一致，若不一致则抛出无权限异常，
     * 若有权限则调用PickAddrService的updateById方法将更新后的提货地址信息保存到数据库中，最后返回成功的响应结果给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"shop:pickAddr:update"权限的用户才能访问此方法。
     *
     * @param pickAddr 包含要更新的提货地址信息的请求体对象，如地址名称、详细地址等属性。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行更新操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('shop:pickAddr:update')")
    public ServerResponseEntity<Void> update(@Valid @RequestBody PickAddr pickAddr) {
        PickAddr dbPickAddr = pickAddrService.getById(pickAddr.getAddrId());

        if (!Objects.equals(dbPickAddr.getShopId(), SecurityUtils.getSysUser().getShopId())) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        pickAddrService.updateById(pickAddr);
        return ServerResponseEntity.success();
    }

    /**
     * 删除提货地址信息的方法，接收一个包含要删除的提货地址ID数组的请求体，通过PickAddrService的removeByIds方法，
     * 将传入的ID数组转换为列表后批量删除对应的提货地址信息，最后返回成功的响应结果给前端。
     * 通过@PreAuthorize注解进行权限控制，只有具备"shop:pickAddr:delete"权限的用户才能访问此方法。
     *
     * @param ids 包含要删除的提货地址ID的数组。
     * @return 返回表示操作成功的ServerResponseEntity对象，由于这里只是执行删除操作，无需返回具体数据，所以返回的是Void类型的成功响应。
     */
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('shop:pickAddr:delete')")
    public ServerResponseEntity<Void> delete(@RequestBody Long[] ids) {
        pickAddrService.removeByIds(Arrays.asList(ids));
        return ServerResponseEntity.success();
    }
}