package org.hzhub.workflow.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hzhub.common.core.constant.SystemConstants;
import org.hzhub.common.tenant.helper.TenantHelper;
import org.hzhub.system.domain.SysDept;
import org.hzhub.system.domain.SysUser;
import org.hzhub.system.domain.bo.SysUserBo;
import org.hzhub.system.mapper.SysDeptMapper;
import org.hzhub.system.mapper.SysUserMapper;
import org.hzhub.system.service.ISysUserService;
import org.hzhub.workflow.service.IWecomUserSyncService;
import org.hzhub.workflow.service.IWecomTenantConfigService;
import org.hzhub.workflow.wecom.WecomApiClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 企业微信用户同步服务实现
 * <p>通过 ISysUserService 创建/更新用户，确保 tenant_id、del_flag 等字段正确设置</p>
 *
 * @author hzhub
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WecomUserSyncServiceImpl implements IWecomUserSyncService {

    private final WecomApiClient wecomApiClient;
    private final ISysUserService userService;
    private final SysUserMapper userMapper;
    private final SysDeptMapper deptMapper;
    private final IWecomTenantConfigService tenantConfigService;

    /**
     * 默认密码（同步的用户初始密码）
     */
    private static final String DEFAULT_PASSWORD = "wecom123!@#";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String syncFromWecom() {
        if (!isConfigured()) {
            return "企业微信未配置，无法同步";
        }

        log.info("开始同步企业微信用户数据");

        // 获取部门ID映射（deptCategory -> sys_dept.deptId）
        Map<Integer, Long> wecomIdToSysDeptId = buildDeptIdMapping();

        // 获取企业微信用户列表（部门ID=1，包含子部门）
        String resp = wecomApiClient.listUsers(1, 1);
        var json = JSONUtil.parseObj(resp);
        int errcode = json.getInt("errcode", -1);
        if (errcode != 0) {
            String errmsg = json.getStr("errmsg");
            log.error("获取企业微信用户列表失败: {}", errmsg);
            return "同步失败: " + errmsg;
        }

        JSONArray userArray = json.getJSONArray("userlist");
        if (userArray == null || userArray.isEmpty()) {
            return "企业微信无用户数据";
        }

        // 查询当前租户下所有用户，建立匹配索引
        List<SysUser> allUsers = TenantHelper.ignore(() -> userMapper.selectList(
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysUser>()
                .isNotNull(SysUser::getOpenId)
        ));

        Map<String, SysUser> existingByPhone = new HashMap<>();
        Map<String, SysUser> existingByOpenId = new HashMap<>();
        for (SysUser u : allUsers) {
            if (u.getPhonenumber() != null) {
                existingByPhone.put(u.getPhonenumber(), u);
            }
            if (u.getOpenId() != null) {
                existingByOpenId.put(u.getOpenId(), u);
            }
        }

        int created = 0;
        int updated = 0;
        int skipped = 0;

        for (Object obj : userArray) {
            JSONObject userJson = (JSONObject) obj;
            String wecomUserId = userJson.getStr("userid");
            String name = userJson.getStr("name");
            String phone = userJson.getStr("mobile");
            String email = userJson.getStr("email");
            String position = userJson.getStr("position");
            String gender = userJson.getStr("gender");
            JSONArray deptIds = userJson.getJSONArray("department");

            String openId = userJson.getStr("open_userid");
            if (openId == null) {
                openId = wecomUserId;
            }

            try {
                // 匹配策略：先按手机号匹配，再按 openId 匹配
                SysUser existing = null;
                if (phone != null) {
                    existing = existingByPhone.get(phone);
                }
                if (existing == null) {
                    existing = existingByOpenId.get(openId);
                }

                // 确定部门ID
                Long sysDeptId = null;
                if (deptIds != null && !deptIds.isEmpty()) {
                    for (Object did : deptIds) {
                        int wecomDeptId = ((Number) did).intValue();
                        Long mappedDeptId = wecomIdToSysDeptId.get(wecomDeptId);
                        if (mappedDeptId != null) {
                            sysDeptId = mappedDeptId;
                            break;
                        }
                    }
                }

                if (existing != null) {
                    // 更新现有用户
                    SysUserBo bo = new SysUserBo();
                    bo.setUserId(existing.getUserId());
                    bo.setNickName(name);
                    bo.setPhonenumber(phone);
                    bo.setEmail(email);
                    bo.setOpenId(openId);
                    bo.setWecomUserid(wecomUserId);
                    bo.setSex(convertGender(gender));
                    if (sysDeptId != null) {
                        bo.setDeptId(sysDeptId);
                    }
                    bo.setStatus(SystemConstants.NORMAL);
                    userService.updateUser(bo);
                    updated++;
                } else {
                    // 跳过没有手机号的用户（无法登录）
                    if (phone == null || phone.isEmpty()) {
                        log.warn("用户 [{}] 没有手机号，跳过同步", name);
                        skipped++;
                        continue;
                    }

                    // 新增用户
                    SysUserBo bo = new SysUserBo();
                    bo.setUserName(generateUserName(wecomUserId, phone));
                    bo.setNickName(name);
                    bo.setPhonenumber(phone);
                    bo.setEmail(email);
                    bo.setOpenId(openId);
                    bo.setWecomUserid(wecomUserId);
                    bo.setSex(convertGender(gender));
                    bo.setDeptId(sysDeptId);
                    bo.setPassword(BCrypt.hashpw(DEFAULT_PASSWORD));
                    bo.setStatus(SystemConstants.NORMAL);
                    bo.setRemark("企业微信同步用户");
                    userService.insertUser(bo);
                    created++;
                }
            } catch (Exception e) {
                log.error("同步用户 [{}] 失败", name, e);
            }
        }

        String msg = String.format("同步完成，新增 %d 个，更新 %d 个，跳过 %d 个", created, updated, skipped);
        log.info(msg);
        return msg;
    }

    /**
     * 构建 WeCom 部门ID 到 sys_dept.deptId 的映射
     */
    private Map<Integer, Long> buildDeptIdMapping() {
        Map<Integer, Long> mapping = new HashMap<>();
        List<SysDept> allDepts = TenantHelper.ignore(() -> deptMapper.selectList(
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDept>()
                .isNotNull(SysDept::getDeptCategory)
        ));
        for (SysDept d : allDepts) {
            if (d.getDeptCategory() != null) {
                try {
                    int wecomId = Integer.parseInt(d.getDeptCategory());
                    mapping.put(wecomId, d.getDeptId());
                } catch (NumberFormatException ignored) {
                }
            }
        }
        return mapping;
    }

    /**
     * 转换性别：企业微信 "1"=男 "2"=女，系统 "0"=男 "1"=女 "2"=未知
     */
    private String convertGender(String gender) {
        if ("1".equals(gender)) return "0";
        if ("2".equals(gender)) return "1";
        return "2";
    }

    /**
     * 生成用户名：优先使用手机号，否则使用 wecom userid
     */
    private String generateUserName(String wecomUserId, String phone) {
        if (phone != null && !phone.isEmpty()) {
            return phone;
        }
        return "wecom_" + wecomUserId;
    }

    private boolean isConfigured() {
        return tenantConfigService.getByCurrentTenant() != null;
    }
}
