package com.yimeng.okr.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yimeng.okr.dto.DepartmentTreeNode;
import com.yimeng.okr.dto.UserInfo;
import com.yimeng.okr.entity.KpiConfig;
import com.yimeng.okr.entity.OkrObjective;
import com.yimeng.okr.entity.PerformanceFeedback;
import com.yimeng.okr.entity.PerformanceScore;
import com.yimeng.okr.entity.SysDepartment;
import com.yimeng.okr.entity.SysUser;
import com.yimeng.okr.enums.UserRole;
import com.yimeng.okr.exception.BusinessException;
import com.yimeng.okr.mapper.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
public class OrganizationService {

    private final SysDepartmentMapper departmentMapper;
    private final SysUserMapper userMapper;
    private final OkrObjectiveMapper objectiveMapper;
    private final PerformanceScoreMapper scoreMapper;
    private final PerformanceFeedbackMapper feedbackMapper;
    private final KpiConfigMapper kpiConfigMapper;
    private final PasswordEncoder passwordEncoder;
    private final AuthorizationService authorizationService;

    // Department CRUD

    public List<DepartmentTreeNode> getDepartmentTree() {
        List<SysDepartment> allDepts = departmentMapper.selectList(
                new LambdaQueryWrapper<SysDepartment>().orderByAsc(SysDepartment::getSortOrder));
        Map<Long, SysUser> leaders = getLeaderMap();

        List<DepartmentTreeNode> nodes = allDepts.stream().map(dept -> {
            DepartmentTreeNode node = DepartmentTreeNode.from(dept);
            if (dept.getLeaderId() != null && leaders.containsKey(dept.getLeaderId())) {
                node.setLeaderName(leaders.get(dept.getLeaderId()).getRealName());
            }
            return node;
        }).collect(Collectors.toList());

        Map<Long, DepartmentTreeNode> nodeMap = nodes.stream()
                .collect(Collectors.toMap(DepartmentTreeNode::getId, n -> n));
        List<DepartmentTreeNode> roots = new ArrayList<>();
        for (DepartmentTreeNode node : nodes) {
            if (node.getParentId() == null || node.getParentId() == 0) {
                roots.add(node);
            } else {
                DepartmentTreeNode parent = nodeMap.get(node.getParentId());
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        }
        return roots;
    }

    public SysDepartment createDepartment(SysDepartment dept) {
        departmentMapper.insert(dept);
        return dept;
    }

    public void updateDepartment(SysDepartment dept) {
        SysDepartment existing = departmentMapper.selectById(dept.getId());
        if (existing == null) throw new BusinessException(404, "部门不存在");
        departmentMapper.updateById(dept);
    }

    @Transactional
    public void deleteDepartment(Long id) {
        long childCount = departmentMapper.selectCount(
                new LambdaQueryWrapper<SysDepartment>().eq(SysDepartment::getParentId, id));
        if (childCount > 0) throw new BusinessException("请先删除子部门");
        departmentMapper.deleteById(id);
    }

    // User management

    public List<UserInfo> getDepartmentMembers(Long deptId, Long actorId) {
        authorizationService.requireCanViewDepartment(actorId, deptId);
        List<SysUser> users = userMapper.selectList(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getDepartmentId, deptId));
        return users.stream().map(UserInfo::from).collect(Collectors.toList());
    }

    public List<UserInfo> getAllUsers(Long actorId) {
        if (!authorizationService.isHrOrAbove(actorId)) {
            throw new BusinessException(403, "无权限，需要HR管理员或以上权限");
        }
        List<SysUser> users = userMapper.selectList(null);
        return users.stream().map(UserInfo::from).collect(Collectors.toList());
    }

    public void updateUserSuperior(Long userId, Long superiorId) {
        SysUser user = userMapper.selectById(userId);
        if (user == null) throw new BusinessException(404, "用户不存在");
        validateSuperiorAssignment(userId, superiorId);
        user.setSuperiorId(superiorId);
        userMapper.updateById(user);
    }

    public void updateUserDepartment(Long userId, Long departmentId) {
        SysUser user = userMapper.selectById(userId);
        if (user == null) throw new BusinessException(404, "用户不存在");
        user.setDepartmentId(departmentId);
        userMapper.updateById(user);
    }

    public void updateUserPosition(Long userId, String position) {
        SysUser user = userMapper.selectById(userId);
        if (user == null) throw new BusinessException(404, "用户不存在");
        user.setPosition(position);
        userMapper.updateById(user);
    }

    public List<UserInfo> getSubordinates(Long superiorId) {
        List<SysUser> users = userMapper.selectList(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getSuperiorId, superiorId));
        return users.stream().map(UserInfo::from).collect(Collectors.toList());
    }

    public List<UserInfo> getAvailableSuperiors(Long actorId) {
        if (!authorizationService.isHrOrAbove(actorId)) {
            throw new BusinessException(403, "无权限，需要HR管理员或以上权限");
        }
        return getAllUsers(actorId);
    }

    @Transactional
    public UserInfo createUser(Map<String, Object> body) {
        String username = body.get("username").toString();
        long count = userMapper.selectCount(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        if (count > 0) throw new BusinessException("用户名已存在");

        SysUser user = new SysUser();
        user.setUsername(username);
        user.setPasswordHash(passwordEncoder.encode(body.getOrDefault("password", "123456").toString()));
        user.setRealName(body.getOrDefault("realName", "").toString());
        user.setEmail(body.containsKey("email") ? body.get("email").toString() : null);
        user.setPosition(body.containsKey("position") ? body.get("position").toString() : null);
        if (body.containsKey("departmentId") && body.get("departmentId") != null)
            user.setDepartmentId(Long.valueOf(body.get("departmentId").toString()));
        if (body.containsKey("superiorId") && body.get("superiorId") != null)
            user.setSuperiorId(Long.valueOf(body.get("superiorId").toString()));
        if (body.containsKey("role") && body.get("role") != null) {
            try {
                user.setRole(UserRole.valueOf(body.get("role").toString()));
            } catch (IllegalArgumentException e) {
                throw new BusinessException("无效角色: " + body.get("role"));
            }
        } else {
            user.setRole(UserRole.EMPLOYEE);
        }
        user.setStatus("ACTIVE");
        userMapper.insert(user);
        return UserInfo.from(user);
    }

    public void updateUser(Long id, Map<String, Object> body) {
        SysUser user = userMapper.selectById(id);
        if (user == null) throw new BusinessException(404, "用户不存在");
        if (body.containsKey("realName")) user.setRealName(body.get("realName").toString());
        if (body.containsKey("email")) user.setEmail(body.get("email").toString());
        if (body.containsKey("position")) user.setPosition(body.get("position").toString());
        if (body.containsKey("departmentId") && body.get("departmentId") != null)
            user.setDepartmentId(Long.valueOf(body.get("departmentId").toString()));
        if (body.containsKey("superiorId") && body.get("superiorId") != null) {
            validateSuperiorAssignment(id, Long.valueOf(body.get("superiorId").toString()));
            user.setSuperiorId(Long.valueOf(body.get("superiorId").toString()));
        }
        if (body.containsKey("role")) {
            try {
                UserRole newRole = UserRole.valueOf(body.get("role").toString());
                if (user.getRole() == UserRole.SUPER_ADMIN && newRole != UserRole.SUPER_ADMIN) {
                    ensureMoreThanOneSuperAdmin();
                }
                user.setRole(newRole);
            } catch (IllegalArgumentException e) {
                throw new BusinessException("无效角色: " + body.get("role"));
            }
        }
        if (body.containsKey("status") && body.get("status") != null) {
            user.setStatus(body.get("status").toString());
        }
        if (body.containsKey("password") && !body.get("password").toString().isEmpty())
            user.setPasswordHash(passwordEncoder.encode(body.get("password").toString()));
        userMapper.updateById(user);
    }

    public void disableUser(Long id) {
        SysUser user = userMapper.selectById(id);
        if (user == null) throw new BusinessException(404, "用户不存在");
        if (user.getRole() == UserRole.SUPER_ADMIN) {
            ensureMoreThanOneSuperAdmin();
        }
        user.setStatus("DISABLED");
        user.setDisabledAt(LocalDateTime.now());
        userMapper.updateById(user);
    }

    public void markUserLeft(Long id) {
        SysUser user = userMapper.selectById(id);
        if (user == null) throw new BusinessException(404, "用户不存在");
        if (user.getRole() == UserRole.SUPER_ADMIN) {
            ensureMoreThanOneSuperAdmin();
        }
        user.setStatus("LEFT");
        user.setLeftAt(LocalDateTime.now());
        user.setDisabledAt(LocalDateTime.now());
        userMapper.updateById(user);
    }

    public void deleteUser(Long id) {
        SysUser user = userMapper.selectById(id);
        if (user == null) throw new BusinessException(404, "用户不存在");
        if (user.getRole() == UserRole.SUPER_ADMIN) {
            ensureMoreThanOneSuperAdmin();
        }
        long subordinateCount = userMapper.selectCount(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getSuperiorId, id));
        if (subordinateCount > 0) throw new BusinessException("该用户仍有直属下属，不能删除");
        long leaderCount = departmentMapper.selectCount(
                new LambdaQueryWrapper<SysDepartment>().eq(SysDepartment::getLeaderId, id));
        if (leaderCount > 0) throw new BusinessException("该用户仍是部门负责人，不能删除");
        long historyCount = objectiveMapper.selectCount(new LambdaQueryWrapper<OkrObjective>().eq(OkrObjective::getUserId, id))
                + scoreMapper.selectCount(new LambdaQueryWrapper<PerformanceScore>().eq(PerformanceScore::getUserId, id))
                + feedbackMapper.selectCount(new LambdaQueryWrapper<PerformanceFeedback>().eq(PerformanceFeedback::getUserId, id))
                + kpiConfigMapper.selectCount(new LambdaQueryWrapper<KpiConfig>().eq(KpiConfig::getUserId, id));
        if (historyCount > 0) throw new BusinessException("该用户存在历史考核数据，不能删除");
        userMapper.deleteById(id);
    }

    private void validateSuperiorAssignment(Long userId, Long superiorId) {
        if (superiorId == null || superiorId <= 0) return;
        if (Objects.equals(userId, superiorId)) throw new BusinessException("不能将自己设为直属上级");
        if (userMapper.selectById(superiorId) == null) throw new BusinessException(404, "直属上级不存在");
        Set<Long> visited = new HashSet<>();
        Long cursor = superiorId;
        while (cursor != null && cursor > 0) {
            if (!visited.add(cursor)) throw new BusinessException("直属上级关系存在循环");
            if (Objects.equals(cursor, userId)) throw new BusinessException("直属上级关系存在循环");
            SysUser superior = userMapper.selectById(cursor);
            if (superior == null) return;
            cursor = superior.getSuperiorId();
        }
    }

    private void ensureMoreThanOneSuperAdmin() {
        long adminCount = userMapper.selectCount(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getRole, UserRole.SUPER_ADMIN));
        if (adminCount <= 1) throw new BusinessException("至少保留一个超级管理员");
    }

    private Map<Long, SysUser> getLeaderMap() {
        List<SysUser> allUsers = userMapper.selectList(null);
        return allUsers.stream().collect(Collectors.toMap(SysUser::getId, u -> u));
    }

    @Transactional
    public void initSeedData() {
        long deptCount = departmentMapper.selectCount(null);
        if (deptCount > 0) throw new BusinessException("企业数据已存在，请勿重复初始化。如需重置请先删除现有部门和用户。");

        SysDepartment sz = createDept("深圳总部", 0L, 1);
        SysDepartment dev = createDept("开发技术中心", sz.getId(), 2);
        SysDepartment fin = createDept("行财中心", sz.getId(), 3);
        SysDepartment plan = createDept("企划中心", sz.getId(), 4);
        SysDepartment ai = createDept("AI技术中心", sz.getId(), 5);
        SysDepartment gs = createDept("甘肃运营中心", 0L, 6);

        String pw = "emoon123456";
        SysUser hantuo = createUser("hantuo", pw, "韩拓", "hantuo@emoon.com", "CEO / 总经理", sz.getId(), null, UserRole.SUPER_ADMIN);
        SysUser wangkang = createUser("wangkang", pw, "王康", "wangkang@emoon.com", "全栈开发工程师", dev.getId(), hantuo.getId(), UserRole.SUPER_ADMIN);
        SysUser hanchao = createUser("hanchao", pw, "韩朝", "hanzhao@emoon.com", "后端开发工程师", dev.getId(), wangkang.getId(), UserRole.EMPLOYEE);
        SysUser gaoli = createUser("gaoli", pw, "高力", "gaoli@emoon.com", "前端开发工程师", dev.getId(), wangkang.getId(), UserRole.EMPLOYEE);
        SysUser fansicheng = createUser("fansicheng", pw, "樊思呈", "fansicheng@emoon.com", "财务总监", fin.getId(), hantuo.getId(), UserRole.EMPLOYEE);
        SysUser liumeng = createUser("liumeng", pw, "刘萌", "liumeng@emoon.com", "产品经理", plan.getId(), hantuo.getId(), UserRole.EMPLOYEE);
        SysUser fengyuanji = createUser("fengyuanji", pw, "冯元积", "fengyuanji@emoon.com", "区域经理", gs.getId(), hantuo.getId(), UserRole.EMPLOYEE);

        setDeptLeader(sz.getId(), hantuo.getId());
        setDeptLeader(dev.getId(), wangkang.getId());
        setDeptLeader(fin.getId(), fansicheng.getId());
        setDeptLeader(plan.getId(), liumeng.getId());
        setDeptLeader(gs.getId(), fengyuanji.getId());
    }

    private SysDepartment createDept(String name, Long parentId, int sort) {
        SysDepartment d = new SysDepartment();
        d.setName(name); d.setParentId(parentId); d.setSortOrder(sort);
        departmentMapper.insert(d);
        return d;
    }

    private SysUser createUser(String username, String password, String realName, String email,
                                String position, Long deptId, Long superiorId, UserRole role) {
        SysUser u = new SysUser();
        u.setUsername(username); u.setPasswordHash(passwordEncoder.encode(password));
        u.setRealName(realName); u.setEmail(email); u.setPosition(position);
        u.setDepartmentId(deptId); u.setSuperiorId(superiorId); u.setRole(role);
        userMapper.insert(u);
        return u;
    }

    private void setDeptLeader(Long deptId, Long leaderId) {
        SysDepartment d = departmentMapper.selectById(deptId);
        if (d != null) { d.setLeaderId(leaderId); departmentMapper.updateById(d); }
    }
}
