package com.ruoyi.web.modules.role.service.impl;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.web.modules.role.constant.MerchantRoleConstants;
import com.ruoyi.web.modules.role.domain.MerchantRoleQuery;
import com.ruoyi.web.modules.role.domain.MerchantRoleRow;
import com.ruoyi.web.modules.role.dto.MerchantRoleCreateDTO;
import com.ruoyi.web.modules.role.dto.MerchantRoleUpdateDTO;
import com.ruoyi.web.modules.role.mapper.MerchantRoleMapper;
import com.ruoyi.web.modules.role.service.IMerchantRoleService;
import com.ruoyi.web.modules.role.support.MerchantRoleSupport;
import com.ruoyi.web.modules.role.vo.MerchantRoleDetailVO;
import com.ruoyi.web.modules.role.vo.MerchantRoleListVO;

/**
 * 角色管理 Service 实现
 */
@Service
public class MerchantRoleServiceImpl implements IMerchantRoleService
{
    @Autowired
    private MerchantRoleMapper merchantRoleMapper;

    @Autowired
    private MerchantRoleSupport merchantRoleSupport;

    @Autowired
    private ISysRoleService sysRoleService;

    @Autowired
    private ISysMenuService sysMenuService;

    @Override
    public void fillListScope(MerchantRoleQuery query, Long operatorUserId)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantRoleSupport.requireCurrentShopId(merchantId);
        if (query == null)
        {
            throw new ServiceException("参数不能为空");
        }
        query.setShopId(shopId);
    }

    @Override
    public List<MerchantRoleListVO> selectRoleList(MerchantRoleQuery query)
    {
        List<MerchantRoleRow> rows = merchantRoleMapper.selectList(query);
        List<MerchantRoleListVO> result = new ArrayList<>();
        for (MerchantRoleRow row : rows)
        {
            result.add(toListVo(row));
        }
        return result;
    }

    @Override
    public List<TreeSelect> selectMenuTree(Long operatorUserId)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        merchantRoleSupport.requireCurrentShopId(merchantId);
        return sysMenuService.buildMenuTreeSelect(merchantRoleSupport.listAssignableMenus());
    }

    @Override
    public MerchantRoleDetailVO selectRoleDetail(Long roleId, Long operatorUserId)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantRoleSupport.requireCurrentShopId(merchantId);
        MerchantRoleRow row = merchantRoleSupport.requireRoleRow(shopId, roleId);
        MerchantRoleDetailVO vo = toDetailVo(row);
        List<Long> menuIds = merchantRoleMapper.selectMenuIdsByRoleId(roleId);
        vo.setMenuIds(menuIds.toArray(new Long[0]));
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRole(MerchantRoleCreateDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantRoleSupport.requireCurrentShopId(merchantId);
        merchantRoleSupport.validateCreate(dto, shopId);

        SysRole role = new SysRole();
        role.setRoleName(dto.getRoleName());
        role.setRoleKey(merchantRoleSupport.generateRoleKey(shopId));
        role.setRoleSort(MerchantRoleConstants.DEFAULT_ROLE_SORT);
        role.setStatus(StringUtils.isEmpty(dto.getStatus()) ? MerchantRoleConstants.STATUS_NORMAL : dto.getStatus());
        role.setRemark(dto.getRoleDesc());
        role.setMenuIds(dto.getMenuIds());
        role.setCreateBy(operator);
        sysRoleService.insertRole(role);

        merchantRoleMapper.insertShopRole(shopId, role.getRoleId());
        return role.getRoleId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(MerchantRoleUpdateDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantRoleSupport.requireCurrentShopId(merchantId);
        merchantRoleSupport.requireRoleRow(shopId, dto.getRoleId());
        merchantRoleSupport.validateUpdate(dto, shopId);

        SysRole role = new SysRole();
        role.setRoleId(dto.getRoleId());
        role.setRoleName(dto.getRoleName());
        role.setStatus(dto.getStatus());
        role.setRemark(dto.getRoleDesc());
        role.setMenuIds(dto.getMenuIds());
        role.setUpdateBy(operator);
        sysRoleService.updateRole(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoles(Long[] roleIds, Long operatorUserId)
    {
        Long merchantId = merchantRoleSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantRoleSupport.requireCurrentShopId(merchantId);
        if (roleIds == null || roleIds.length == 0)
        {
            return;
        }
        for (Long roleId : roleIds)
        {
            merchantRoleSupport.requireRoleRow(shopId, roleId);
            merchantRoleSupport.assertDeletable(shopId, roleId);
        }
        for (Long roleId : roleIds)
        {
            merchantRoleMapper.deleteShopRole(shopId, roleId);
            sysRoleService.deleteRoleById(roleId);
        }
    }

    private MerchantRoleListVO toListVo(MerchantRoleRow row)
    {
        MerchantRoleListVO vo = new MerchantRoleListVO();
        vo.setRoleId(row.getRoleId());
        vo.setRoleName(row.getRoleName());
        vo.setRoleDesc(StringUtils.isEmpty(row.getRoleDesc()) ? "—" : row.getRoleDesc());
        vo.setStatus(row.getStatus());
        vo.setBindCount(row.getBindCount() != null ? row.getBindCount() : 0);
        vo.setCreateTime(row.getCreateTime());
        return vo;
    }

    private MerchantRoleDetailVO toDetailVo(MerchantRoleRow row)
    {
        MerchantRoleDetailVO vo = new MerchantRoleDetailVO();
        vo.setRoleId(row.getRoleId());
        vo.setRoleName(row.getRoleName());
        vo.setRoleDesc(row.getRoleDesc());
        vo.setStatus(row.getStatus());
        vo.setBindCount(row.getBindCount() != null ? row.getBindCount() : 0);
        vo.setCreateTime(row.getCreateTime());
        return vo;
    }
}
