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

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.account.constant.MerchantEmployeeConstants;
import com.ruoyi.web.modules.account.domain.MerchantEmployeeQuery;
import com.ruoyi.web.modules.account.domain.MerchantEmployeeRow;
import com.ruoyi.web.modules.account.dto.MerchantEmployeeCreateDTO;
import com.ruoyi.web.modules.account.dto.MerchantEmployeePasswordDTO;
import com.ruoyi.web.modules.account.dto.MerchantEmployeeProfileDTO;
import com.ruoyi.web.modules.account.dto.MerchantEmployeeUpdateDTO;
import com.ruoyi.web.modules.account.mapper.MerchantEmployeeMapper;
import com.ruoyi.web.modules.account.service.IMerchantEmployeeService;
import com.ruoyi.web.modules.account.support.MerchantEmployeeSupport;
import com.ruoyi.web.modules.account.util.MemberMobileUtils;
import com.ruoyi.web.modules.account.vo.MerchantEmployeeDetailVO;
import com.ruoyi.web.modules.account.vo.MerchantEmployeeListVO;
import com.ruoyi.web.modules.account.vo.MerchantEmployeeQuotaVO;
import com.ruoyi.web.modules.account.vo.MerchantEmployeeRoleOptionVO;
import com.ruoyi.web.modules.merchant.domain.BizMerchant;
import com.ruoyi.web.modules.merchant.mapper.BizMerchantMapper;
import com.ruoyi.web.modules.store.constant.ShopConstants;
import com.ruoyi.web.modules.store.domain.BizMerchantAccount;
import com.ruoyi.web.modules.store.domain.BizShop;
import com.ruoyi.web.modules.store.facade.IShopGlobalConfigFacade;
import com.ruoyi.web.modules.store.mapper.BizMerchantAccountMapper;
import com.ruoyi.web.modules.store.mapper.BizShopMapper;

/**
 * 员工管理 Service 实现
 */
@Service
public class MerchantEmployeeServiceImpl implements IMerchantEmployeeService
{
    @Autowired
    private MerchantEmployeeMapper merchantEmployeeMapper;

    @Autowired
    private MerchantEmployeeSupport merchantEmployeeSupport;

    @Autowired
    private BizMerchantAccountMapper merchantAccountMapper;

    @Autowired
    private BizMerchantMapper merchantMapper;

    @Autowired
    private BizShopMapper shopMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private IShopGlobalConfigFacade shopGlobalConfigFacade;

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

    @Override
    public List<MerchantEmployeeListVO> selectEmployeeList(MerchantEmployeeQuery query)
    {
        List<MerchantEmployeeRow> rows = merchantEmployeeMapper.selectList(query);
        List<MerchantEmployeeListVO> result = new ArrayList<>();
        for (MerchantEmployeeRow row : rows)
        {
            result.add(toListVo(row));
        }
        return result;
    }

    @Override
    public MerchantEmployeeQuotaVO selectQuota(Long operatorUserId)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        MerchantEmployeeQuotaVO vo = new MerchantEmployeeQuotaVO();
        vo.setMerchantId(merchantId);
        BizMerchant merchant = merchantMapper.selectById(merchantId);
        vo.setMerchantName(merchant != null ? merchant.getMerchantName() : "");
        vo.setShopId(shopId);
        BizShop shop = shopMapper.selectById(shopId);
        vo.setShopName(shop != null ? shop.getShopName() : "");
        vo.setUsedCount(merchantAccountMapper.countEmployeesByMerchantId(merchantId));
        Integer max = shopGlobalConfigFacade.getMaxSubAdmin();
        vo.setMaxCount(max != null ? max : ShopConstants.DEFAULT_MAX_SUB_ADMIN);
        return vo;
    }

    @Override
    public List<MerchantEmployeeRoleOptionVO> selectRoleOptions(Long operatorUserId)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        return merchantEmployeeMapper.selectRoleOptions(shopId);
    }

    @Override
    public MerchantEmployeeDetailVO selectEmployeeDetail(Long userId, Long operatorUserId)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        MerchantEmployeeRow row = merchantEmployeeMapper.selectByUserId(merchantId, shopId, userId);
        if (row == null)
        {
            throw new ServiceException(MerchantEmployeeConstants.MSG_NOT_FOUND);
        }
        return toDetailVo(row, shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createEmployee(MerchantEmployeeCreateDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        merchantEmployeeSupport.assertQuotaAvailable(merchantId);
        merchantEmployeeSupport.validateCreate(dto, shopId);
        assertMobileUnique(null, dto.getMobile());

        SysUser sysUser = new SysUser();
        sysUser.setDeptId(MerchantEmployeeConstants.DEFAULT_DEPT_ID);
        sysUser.setUserName(dto.getMobile());
        sysUser.setNickName(dto.getEmployeeName());
        sysUser.setPhonenumber(dto.getMobile());
        sysUser.setEmail(dto.getEmail());
        sysUser.setAvatar(dto.getAvatar());
        sysUser.setStatus(StringUtils.isEmpty(dto.getStatus()) ? MerchantEmployeeConstants.STATUS_NORMAL : dto.getStatus());
        sysUser.setPassword(SecurityUtils.encryptPassword(UUID.randomUUID().toString()));
        sysUser.setCreateBy(operator);
        sysUser.setRoleIds(dto.getRoleIds());
        sysUserService.insertUser(sysUser);

        BizMerchantAccount account = new BizMerchantAccount();
        account.setAccountId(sysUser.getUserId());
        account.setMerchantId(merchantId);
        account.setShopId(shopId);
        account.setDelFlag(ShopConstants.DEL_NORMAL);
        account.setCreateBy(operator);
        merchantAccountMapper.insert(account);
        return sysUser.getUserId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEmployee(MerchantEmployeeUpdateDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        merchantEmployeeSupport.requireEmployeeRow(merchantId, shopId, dto.getUserId());
        merchantEmployeeSupport.validateUpdate(dto, shopId);

        SysUser existing = sysUserService.selectUserById(dto.getUserId());
        String currentMobile = existing.getUserName();
        if (!currentMobile.equals(dto.getMobile()))
        {
            assertMobileUnique(dto.getUserId(), dto.getMobile());
        }

        merchantAccountMapper.updateSysUserProfile(
                dto.getUserId(),
                currentMobile.equals(dto.getMobile()) ? null : dto.getMobile(),
                dto.getEmployeeName(),
                dto.getEmail(),
                currentMobile.equals(dto.getMobile()) ? null : dto.getMobile(),
                null,
                operator);

        SysUser statusUpdate = new SysUser();
        statusUpdate.setUserId(dto.getUserId());
        statusUpdate.setStatus(dto.getStatus());
        statusUpdate.setAvatar(dto.getAvatar());
        statusUpdate.setUpdateBy(operator);
        sysUserMapper.updateUser(statusUpdate);

        replaceEmployeeRoles(dto.getUserId(), dto.getRoleIds());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProfile(MerchantEmployeeProfileDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        merchantEmployeeSupport.requireEmployeeRow(merchantId, shopId, dto.getUserId());
        merchantEmployeeSupport.validateProfile(dto);

        SysUser existing = sysUserService.selectUserById(dto.getUserId());
        String currentMobile = existing.getUserName();
        if (!currentMobile.equals(dto.getMobile()))
        {
            assertMobileUnique(dto.getUserId(), dto.getMobile());
        }

        merchantAccountMapper.updateSysUserProfile(
                dto.getUserId(),
                currentMobile.equals(dto.getMobile()) ? null : dto.getMobile(),
                dto.getEmployeeName(),
                dto.getEmail(),
                currentMobile.equals(dto.getMobile()) ? null : dto.getMobile(),
                null,
                operator);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(MerchantEmployeePasswordDTO dto, Long operatorUserId, String operator)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        merchantEmployeeSupport.requireEmployeeRow(merchantId, shopId, dto.getUserId());
        merchantEmployeeSupport.validatePasswordUpdate(dto);

        String passwordHash = SecurityUtils.encryptPassword(dto.getPassword());
        merchantAccountMapper.updateSysUserProfile(
                dto.getUserId(),
                null,
                null,
                null,
                null,
                passwordHash,
                operator);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteEmployees(Long[] userIds, Long operatorUserId, String operator)
    {
        Long merchantId = merchantEmployeeSupport.requireMerchantId(operatorUserId);
        Long shopId = merchantEmployeeSupport.requireCurrentShopId(merchantId);
        if (userIds == null || userIds.length == 0)
        {
            return;
        }
        for (Long userId : userIds)
        {
            merchantEmployeeSupport.requireEmployeeRow(merchantId, shopId, userId);
        }
        for (Long userId : userIds)
        {
            merchantAccountMapper.logicDeleteEmployeeByUserId(userId, operator);
            sysUserRoleMapper.deleteUserRoleByUserId(userId);
            sysUserMapper.deleteUserById(userId);
        }
    }

    private void replaceEmployeeRoles(Long userId, Long[] roleIds)
    {
        sysUserRoleMapper.deleteUserRoleByUserId(userId);
        sysUserService.insertUserAuth(userId, roleIds);
    }

    private void assertMobileUnique(Long userId, String mobile)
    {
        SysUser check = new SysUser();
        check.setUserId(userId);
        check.setUserName(mobile);
        if (!sysUserService.checkUserNameUnique(check))
        {
            throw new ServiceException(MerchantEmployeeConstants.MSG_MOBILE_EXISTS);
        }
    }

    private MerchantEmployeeListVO toListVo(MerchantEmployeeRow row)
    {
        MerchantEmployeeListVO vo = new MerchantEmployeeListVO();
        vo.setUserId(row.getUserId());
        vo.setLoginAccount(row.getUserName());
        vo.setEmployeeName(row.getNickName());
        vo.setMobile(MemberMobileUtils.mask(merchantEmployeeSupport.resolveMobile(row)));
        vo.setEmail(StringUtils.isEmpty(row.getEmail()) ? "—" : row.getEmail());
        vo.setStatus(row.getStatus());
        vo.setAccountType(row.getAccountType());
        vo.setOperable(row.isEmployee());
        vo.setCreateTime(row.getCreateTime());
        return vo;
    }

    private MerchantEmployeeDetailVO toDetailVo(MerchantEmployeeRow row, Long shopId)
    {
        MerchantEmployeeDetailVO vo = new MerchantEmployeeDetailVO();
        vo.setUserId(row.getUserId());
        vo.setLoginAccount(row.getUserName());
        vo.setEmployeeName(row.getNickName());
        vo.setMobile(merchantEmployeeSupport.resolveMobile(row));
        vo.setEmail(row.getEmail());
        vo.setAvatar(row.getAvatar());
        vo.setStatus(row.getStatus());
        vo.setAccountType(row.getAccountType());
        vo.setOperable(row.isEmployee());
        vo.setShopId(row.getShopId());
        vo.setCreateTime(row.getCreateTime());
        if (row.isEmployee())
        {
            List<Long> roleIds = merchantEmployeeMapper.selectRoleIdsByUserId(row.getUserId(), shopId);
            vo.setRoleIds(roleIds.toArray(new Long[0]));
        }
        return vo;
    }
}
