/*
 * 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.Transport;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.TransportService;
import org.apache.commons.lang3.StringUtils;
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 java.util.Date;
import java.util.List;

/**
 * 运费模板（Transport）相关操作的控制器类，用于处理后台对运费模板的各种请求，
 * 例如分页查询、获取详情、保存、修改、删除以及获取运费模板列表等操作。
 *
 * @author lgh on 2018/11/16.
 */
@RestController
@RequestMapping("/shop/transport")
public class TransportController {

    // 自动注入运费模板服务层接口，通过该接口调用具体的业务逻辑方法来处理运费模板相关业务
    @Autowired
    private TransportService transportService;

    /**
     * 分页获取运费模板信息的方法
     * 此方法根据传入的运费模板查询条件（Transport）以及分页参数（PageParam），查询并返回符合条件的运费模板信息分页结果。
     * 只有拥有 'shop:transport:page' 权限的用户才能访问此方法。
     * 会根据当前登录用户所属店铺的 ID 进行筛选，确保只获取该店铺相关的运费模板记录，同时支持根据运费模板名称进行模糊查询。
     *
     * @param transport 运费模板查询条件对象，可设置如名称等属性用于筛选数据
     * @param page 分页对象，包含页码、每页数量等分页相关参数
     * @return 包含运费模板信息的分页数据，封装在 ServerResponseEntity 中，方便统一的响应格式处理
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('shop:transport:page')")
    public ServerResponseEntity<IPage<Transport>> page(Transport transport, PageParam<Transport> page) {
        // 获取当前登录用户所属店铺的 ID，用于筛选当前店铺的运费模板数据
        Long shopId = SecurityUtils.getSysUser().getShopId();
        IPage<Transport> transports = transportService.page(page,
                new LambdaQueryWrapper<Transport>()
                        // 根据店铺 ID 精确匹配，筛选出属于当前店铺的运费模板记录
                       .eq(Transport::getShopId, shopId)
                        // 如果传入的运费模板名称不为空，则进行模糊匹配名称字段进行查询，实现根据名称筛选的功能
                       .like(StringUtils.isNotBlank(transport.getTransName()), Transport::getTransName, transport.getTransName()));
        return ServerResponseEntity.success(transports);
    }

    /**
     * 根据给定的 ID 获取运费模板详细信息的方法
     * 此方法接收一个运费模板的 ID，通过调用服务层的方法从数据库中获取对应的详细信息，包括运费模板及其所有关联项信息，
     * 并将结果封装在 ServerResponseEntity 中返回给前端，只有拥有 'shop:transport:info' 权限的用户才能访问此方法。
     *
     * @param id 要查询的运费模板记录的 ID
     * @return 包含运费模板详细信息的 ServerResponseEntity，若查询到则返回对应的数据，否则返回相应的空数据表示
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("@pms.hasPermission('shop:transport:info')")
    public ServerResponseEntity<Transport> info(@PathVariable("id") Long id) {
        Transport transport = transportService.getTransportAndAllItems(id);
        return ServerResponseEntity.success(transport);
    }

    /**
     * 保存运费模板信息的方法
     * 此方法接收一个包含运费模板信息的 Transport 对象，设置记录的所属店铺 ID（从当前登录用户获取）以及创建时间为当前时间，
     * 然后调用服务层的方法将运费模板及其相关的运费信息保存到数据库中，只有拥有 'shop:transport:save' 权限的用户才能执行此操作。
     *
     * @param transport 包含要保存的运费模板信息的对象，其属性应符合数据库对应表的字段要求
     * @return 表示保存操作成功的 ServerResponseEntity，用于告知前端保存操作已顺利完成
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('shop:transport:save')")
    public ServerResponseEntity<Void> save(@RequestBody Transport transport) {
        // 获取当前登录用户所属店铺的 ID，设置到运费模板对象中，明确该运费模板所属的店铺
        Long shopId = SecurityUtils.getSysUser().getShopId();
        transport.setShopId(shopId);
        // 创建当前时间对象，作为运费模板的创建时间
        Date createTime = new Date();
        transport.setCreateTime(createTime);
        transportService.insertTransportAndTransfee(transport);
        return ServerResponseEntity.success();
    }

    /**
     * 修改运费模板信息的方法
     * 此方法接收一个包含更新后运费模板信息的 Transport 对象，调用服务层的方法将数据库中的对应运费模板及其相关运费信息进行更新，
     * 只有拥有 'shop:transport:update' 权限的用户才能执行此操作，更新成功后返回表示操作成功的 ServerResponseEntity 给前端。
     *
     * @param transport 包含要修改的运费模板信息的对象，其属性应符合数据库对应表的字段要求
     * @return 表示修改操作成功的 ServerResponseEntity，用于告知前端修改操作已顺利完成
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('shop:transport:update')")
    public ServerResponseEntity<Void> update(@RequestBody Transport transport) {
        transportService.updateTransportAndTransfee(transport);
        return ServerResponseEntity.success();
    }

    /**
     * 删除运费模板的方法
     * 此方法接收一个包含多个运费模板 ID 的数组，调用服务层的方法从数据库中批量删除这些运费模板及其相关的运费、运输城市等信息，
     * 并且在删除后会循环遍历删除的 ID，清除对应运费模板及其所有关联项的缓存，只有拥有 'shop:transport:delete' 权限的用户才能执行此操作，
     * 最后返回表示删除操作成功的 ServerResponseEntity 给前端。
     *
     * @param ids 包含要删除的运费模板记录的 ID 数组
     * @return 表示删除操作成功的 ServerResponseEntity，用于告知前端删除操作已顺利完成
     */
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('shop:transport:delete')")
    public ServerResponseEntity<Void> delete(@RequestBody Long[] ids) {
        transportService.deleteTransportAndTransfeeAndTranscity(ids);
        // 删除运费模板的缓存，确保缓存数据与数据库最新数据一致，避免缓存数据造成的不一致问题
        for (Long id : ids) {
            transportService.removeTransportAndAllItemsCache(id);
        }
        return ServerResponseEntity.success();
    }

    /**
     * 获取当前店铺的运费模板列表的方法
     * 此方法通过调用服务层的方法，根据当前登录用户所属店铺的 ID 查询并获取该店铺下的所有运费模板列表，
     * 将结果封装在 ServerResponseEntity 中返回给前端，方便前端展示和使用运费模板数据。
     *
     * @return 包含运费模板列表数据的 ServerResponseEntity，若查询到则返回对应的数据列表，否则返回空列表表示
     */
    @GetMapping("/list")
    public ServerResponseEntity<List<Transport>> list() {
        // 获取当前登录用户所属店铺的 ID，用于筛选当前店铺的运费模板数据
        Long shopId = SecurityUtils.getSysUser().getShopId();
        List<Transport> list = transportService.list(new LambdaQueryWrapper<Transport>().eq(Transport::getShopId, shopId));
        return ServerResponseEntity.success(list);
    }
}