package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lesingle.creation.dto.department.CreateDepartmentDTO;
import com.lesingle.creation.dto.department.UpdateDepartmentDTO;
import com.lesingle.creation.entity.Department;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.mapper.DepartmentMapper;
import com.lesingle.creation.service.DepartmentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.creation.vo.department.DepartmentVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 部门服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {

    private final DepartmentMapper departmentMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DepartmentVO create(CreateDepartmentDTO dto, Long tenantId, Long creatorId) {
        // 检查部门编码是否已存在
        Department existing = departmentMapper.selectByCode(tenantId, dto.getCode());
        if (existing != null) {
            throw new BusinessException("部门编码已存在");
        }

        Department department = new Department();
        department.setTenantId(tenantId);
        department.setName(dto.getName());
        department.setCode(dto.getCode());
        department.setParentId(dto.getParentId());
        department.setDescription(dto.getDescription());
        department.setSort(dto.getSort() != null ? dto.getSort() : 0);
        department.setValidState(1);

        departmentMapper.insert(department);
        log.info("创建部门成功，ID={}, 名称={}", department.getId(), dto.getName());

        return convertToVO(department);
    }

    @Override
    public List<DepartmentVO> list(Long tenantId, Long parentId) {
        LambdaQueryWrapper<Department> wrapper = new LambdaQueryWrapper<Department>()
                .eq(Department::getTenantId, tenantId)
                .eq(Department::getDeleted, 0)
                .eq(parentId != null, Department::getParentId, parentId)
                .orderByAsc(Department::getSort);

        List<Department> departments = this.list(wrapper);
        return departments.stream().map(this::convertToVO).collect(Collectors.toList());
    }

    @Override
    public List<DepartmentVO> tree(Long tenantId) {
        // 查询所有顶级部门（parentId 为 null 或 0）
        List<Department> allDepartments = this.list(new LambdaQueryWrapper<Department>()
                .eq(Department::getTenantId, tenantId)
                .eq(Department::getDeleted, 0)
                .orderByAsc(Department::getSort));

        // 构建树形结构
        return buildDepartmentTree(allDepartments, null);
    }

    @Override
    public DepartmentVO getDetail(Long id, Long tenantId) {
        Department department = this.getById(id);
        if (department == null || !department.getTenantId().equals(tenantId)) {
            throw new BusinessException("部门不存在");
        }
        return convertToVO(department);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DepartmentVO update(Long id, UpdateDepartmentDTO dto, Long tenantId, Long modifierId) {
        Department department = this.getById(id);
        if (department == null || !department.getTenantId().equals(tenantId)) {
            throw new BusinessException("部门不存在");
        }

        if (dto.getCode() != null) {
            // 检查新编码是否已被其他部门使用
            Department existing = departmentMapper.selectByCode(tenantId, dto.getCode());
            if (existing != null && !existing.getId().equals(id)) {
                throw new BusinessException("部门编码已存在");
            }
            department.setCode(dto.getCode());
        }
        if (dto.getName() != null) {
            department.setName(dto.getName());
        }
        if (dto.getParentId() != null) {
            // 不能将自己设置为父部门
            if (dto.getParentId().equals(id)) {
                throw new BusinessException("不能将自己设置为父部门");
            }
            department.setParentId(dto.getParentId());
        }
        if (dto.getDescription() != null) {
            department.setDescription(dto.getDescription());
        }
        if (dto.getSort() != null) {
            department.setSort(dto.getSort());
        }
        if (dto.getValidState() != null) {
            department.setValidState(dto.getValidState());
        }

        this.updateById(department);
        log.info("更新部门成功，ID={}", id);

        return convertToVO(department);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id, Long tenantId) {
        Department department = this.getById(id);
        if (department == null || !department.getTenantId().equals(tenantId)) {
            throw new BusinessException("部门不存在");
        }

        // 检查是否有子部门
        Long childCount = this.count(new LambdaQueryWrapper<Department>()
                .eq(Department::getParentId, id)
                .eq(Department::getDeleted, 0));
        if (childCount > 0) {
            throw new BusinessException("存在子部门，无法删除");
        }

        department.setDeleted(1);
        this.updateById(department);
        log.info("删除部门成功，ID={}", id);
    }

    private DepartmentVO convertToVO(Department department) {
        DepartmentVO vo = new DepartmentVO();
        vo.setId(department.getId());
        vo.setTenantId(department.getTenantId());
        vo.setName(department.getName());
        vo.setCode(department.getCode());
        vo.setParentId(department.getParentId());
        vo.setDescription(department.getDescription());
        vo.setSort(department.getSort());
        vo.setValidState(department.getValidState());
        vo.setCreateTime(department.getCreateTime());
        vo.setUpdateTime(department.getUpdateTime());
        return vo;
    }

    private List<DepartmentVO> buildDepartmentTree(List<Department> allDepartments, Long parentId) {
        List<DepartmentVO> tree = allDepartments.stream()
                .filter(dept -> {
                    if (parentId == null) {
                        return dept.getParentId() == null || dept.getParentId() == 0;
                    }
                    return parentId.equals(dept.getParentId());
                })
                .map(this::convertToVO)
                .sorted(Comparator.comparing(DepartmentVO::getSort))
                .collect(Collectors.toList());

        // 递归构建子部门
        for (DepartmentVO node : tree) {
            List<DepartmentVO> children = buildDepartmentTree(allDepartments, node.getId());
            if (!children.isEmpty()) {
                node.setChildren(children);
            }
        }

        return tree;
    }
}
