package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.dto.tenant.CreateTenantDTO;
import com.lesingle.creation.dto.tenant.UpdateTenantDTO;
import com.lesingle.creation.entity.Tenant;
import com.lesingle.creation.entity.TenantMenu;
import com.lesingle.creation.entity.User;
import com.lesingle.creation.mapper.TenantMapper;
import com.lesingle.creation.mapper.UserMapper;
import com.lesingle.creation.service.TenantMenuService;
import com.lesingle.creation.service.TenantService;
import com.lesingle.creation.vo.tenant.TenantDetailVO;
import com.lesingle.creation.vo.tenant.TenantListVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 租户服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService {

    private final TenantMapper tenantMapper;
    private final TenantMenuService tenantMenuService;
    private final UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TenantDetailVO create(CreateTenantDTO dto, Long creatorId) {
        log.info("开始创建租户，租户编码：{}", dto.getCode());

        // 检查租户编码是否已存在
        Tenant existingTenant = tenantMapper.selectByCode(dto.getCode());
        if (existingTenant != null) {
            throw new BusinessException("租户编码已存在");
        }

        // 如果提供了域名，检查域名是否已存在
        if (dto.getDomain() != null && !dto.getDomain().isEmpty()) {
            Tenant existingDomain = tenantMapper.selectByDomain(dto.getDomain());
            if (existingDomain != null) {
                throw new BusinessException("租户域名已存在");
            }
        }

        // 创建租户
        Tenant tenant = new Tenant();
        tenant.setName(dto.getName());
        tenant.setCode(dto.getCode());
        tenant.setDomain(dto.getDomain());
        tenant.setDescription(dto.getDescription());
        tenant.setTenantType(dto.getTenantType() != null ? dto.getTenantType() : "other");
        tenant.setValidState(1);
        tenant.setCreateBy(creatorId != null ? String.valueOf(creatorId) : "system");

        tenantMapper.insert(tenant);
        log.info("租户创建成功，租户 ID: {}", tenant.getId());

        // 如果提供了菜单 ID，创建菜单关联
        if (!CollectionUtils.isEmpty(dto.getMenuIds())) {
            List<TenantMenu> tenantMenus = dto.getMenuIds().stream()
                    .map(menuId -> {
                        TenantMenu tm = new TenantMenu();
                        tm.setTenantId(tenant.getId());
                        tm.setMenuId(menuId);
                        return tm;
                    })
                    .collect(Collectors.toList());
            tenantMenuService.saveBatch(tenantMenus);
            log.info("租户菜单关联创建成功，菜单数量：{}", dto.getMenuIds().size());
        }

        return convertToDetailVO(tenant);
    }

    @Override
    public Page<TenantListVO> pageList(int page, int pageSize) {
        log.info("分页查询租户列表，页码：{}, 每页大小：{}", page, pageSize);

        Page<Tenant> tenantPage = new Page<>(page, pageSize);
        LambdaQueryWrapper<Tenant> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Tenant::getCreateTime);

        Page<Tenant> resultPage = tenantMapper.selectPage(tenantPage, wrapper);

        // 转换为 VO
        List<TenantListVO> voList = resultPage.getRecords().stream()
                .map(this::convertToListVO)
                .collect(Collectors.toList());

        Page<TenantListVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(voList);

        return voPage;
    }

    @Override
    public TenantDetailVO detail(Long id) {
        log.info("查询租户详情，租户 ID: {}", id);

        Tenant tenant = tenantMapper.selectById(id);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }

        return convertToDetailVO(tenant);
    }

    @Override
    public TenantDetailVO getByCode(String code) {
        log.info("根据编码查询租户，编码：{}", code);

        Tenant tenant = tenantMapper.selectByCode(code);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }

        return convertToDetailVO(tenant);
    }

    @Override
    public TenantDetailVO getByDomain(String domain) {
        log.info("根据域名查询租户，域名：{}", domain);

        Tenant tenant = tenantMapper.selectByDomain(domain);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }

        return convertToDetailVO(tenant);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TenantDetailVO update(Long id, UpdateTenantDTO dto, Long modifierId) {
        log.info("更新租户，租户 ID: {}, 修改人 ID: {}", id, modifierId);

        // 检查租户是否存在
        Tenant existingTenant = tenantMapper.selectById(id);
        if (existingTenant == null) {
            throw new BusinessException("租户不存在");
        }

        // 如果更新了 code，检查是否冲突
        if (dto.getCode() != null && !dto.getCode().isEmpty()) {
            Tenant conflictTenant = tenantMapper.selectByCodeExclude(dto.getCode(), id);
            if (conflictTenant != null) {
                throw new BusinessException("租户编码已存在");
            }
        }

        // 如果更新了 domain，检查是否冲突
        if (dto.getDomain() != null && !dto.getDomain().isEmpty()) {
            Tenant conflictDomain = tenantMapper.selectByDomainExclude(dto.getDomain(), id);
            if (conflictDomain != null) {
                throw new BusinessException("租户域名已存在");
            }
        }

        // 更新租户信息
        Tenant tenant = new Tenant();
        tenant.setId(id);
        tenant.setName(dto.getName());
        tenant.setCode(dto.getCode());
        tenant.setDomain(dto.getDomain());
        tenant.setDescription(dto.getDescription());
        tenant.setValidState(dto.getValidState());
        tenant.setUpdateBy(modifierId != null ? String.valueOf(modifierId) : "system");

        tenantMapper.updateById(tenant);
        log.info("租户更新成功，租户 ID: {}", id);

        // 如果提供了 menuIds，更新菜单关联
        if (dto.getMenuIds() != null) {
            // 先删除现有菜单关联
            LambdaQueryWrapper<TenantMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantMenu::getTenantId, id);
            tenantMenuService.remove(wrapper);
            log.info("已删除租户原有菜单关联");

            // 创建新的菜单关联
            if (!dto.getMenuIds().isEmpty()) {
                List<TenantMenu> tenantMenus = dto.getMenuIds().stream()
                        .map(menuId -> {
                            TenantMenu tm = new TenantMenu();
                            tm.setTenantId(id);
                            tm.setMenuId(menuId);
                            return tm;
                        })
                        .collect(Collectors.toList());
                tenantMenuService.saveBatch(tenantMenus);
                log.info("租户新菜单关联创建成功，菜单数量：{}", dto.getMenuIds().size());
            }
        }

        return convertToDetailVO(tenantMapper.selectById(id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        log.info("删除租户，租户 ID: {}", id);

        // 检查租户是否存在
        Tenant tenant = tenantMapper.selectById(id);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }

        // 检查是否为超级租户
        if (tenant.getIsSuper() != null && tenant.getIsSuper() == 1) {
            throw new BusinessException("不能删除超级租户");
        }

        // 删除租户（逻辑删除）
        tenantMapper.deleteById(id);
        log.info("租户删除成功，租户 ID: {}", id);
    }

    @Override
    public List<?> getTenantMenus(Long tenantId) {
        log.info("获取租户菜单，租户 ID: {}", tenantId);

        // 检查租户是否存在
        Tenant tenant = tenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }

        // TODO: 实现获取租户菜单树逻辑
        return new ArrayList<>();
    }

    /**
     * 转换为详情 VO
     */
    private TenantDetailVO convertToDetailVO(Tenant tenant) {
        TenantDetailVO vo = new TenantDetailVO();
        vo.setId(tenant.getId());
        vo.setName(tenant.getName());
        vo.setCode(tenant.getCode());
        vo.setDomain(tenant.getDomain());
        vo.setDescription(tenant.getDescription());
        vo.setIsSuper(tenant.getIsSuper());
        vo.setTenantType(tenant.getTenantType());
        vo.setValidState(tenant.getValidState());
        vo.setCreateBy(tenant.getCreateBy());
        vo.setCreateTime(tenant.getCreateTime());
        vo.setUpdateBy(tenant.getUpdateBy());
        vo.setUpdateTime(tenant.getUpdateTime());

        // 统计用户数量和角色数量（需要时实现）
        vo.setUserCount(0);
        vo.setRoleCount(0);

        return vo;
    }

    /**
     * 转换为列表 VO
     */
    private TenantListVO convertToListVO(Tenant tenant) {
        TenantListVO vo = new TenantListVO();
        vo.setId(tenant.getId());
        vo.setName(tenant.getName());
        vo.setCode(tenant.getCode());
        vo.setDomain(tenant.getDomain());
        vo.setDescription(tenant.getDescription());
        vo.setIsSuper(tenant.getIsSuper());
        vo.setTenantType(tenant.getTenantType());
        vo.setValidState(tenant.getValidState());
        vo.setCreateTime(tenant.getCreateTime());

        // 统计用户数量和角色数量（需要时实现）
        vo.setUserCount(0);
        vo.setRoleCount(0);

        return vo;
    }
}
