package com.rj.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.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rj.common.DictItemConstants;
import com.rj.common.PasswordUtil;
import com.rj.common.QiWeiApiConstants;
import com.rj.dto.QiWeiConfig;
import com.rj.entity.DictItem;
import com.rj.entity.QweiDepartment;
import com.rj.mapper.DictItemMapper;
import com.rj.mapper.QweiDepartmentMapper;
import com.rj.service.IQweiDepartmentService;
import com.rj.tenant.TenantContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class QweiDepartmentServiceImpl extends ServiceImpl<QweiDepartmentMapper, QweiDepartment>
        implements IQweiDepartmentService {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();

    @Autowired
    private DictItemMapper dictItemMapper;

    @Override
    public Map<String, Object> add(QweiDepartment entity) {
        Map<String, Object> result = new HashMap<>();
        try {
            String tenantId = resolveTenantId(entity.getTenantId());
            if (entity.getDeptId() == null) {
                result.put("success", false);
                result.put("message", "deptId不能为空");
                return result;
            }
            if (entity.getDeptName() == null || entity.getDeptName().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "deptName不能为空");
                return result;
            }
            LambdaQueryWrapper<QweiDepartment> dup = new LambdaQueryWrapper<QweiDepartment>()
                    .eq(QweiDepartment::getDeptId, entity.getDeptId());
            if (this.count(dup) > 0) {
                result.put("success", false);
                result.put("message", "deptId已存在");
                return result;
            }

            entity.setId(UUID.randomUUID().toString());
            entity.setTenantId(tenantId);
            if (entity.getIsDeleted() == null) {
                entity.setIsDeleted(0);
            }
            LocalDateTime now = LocalDateTime.now();
            entity.setCreatedAt(now);
            entity.setUpdatedAt(now);
            boolean ok = this.save(entity);
            result.put("success", ok);
            result.put("message", ok ? "添加成功" : "添加失败");
            if (ok) {
                result.put("data", entity);
            }
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "添加异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    public Map<String, Object> update(QweiDepartment entity) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (entity.getId() == null || entity.getId().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "id不能为空");
                return result;
            }
            entity.setUpdatedAt(LocalDateTime.now());
            boolean ok = this.updateById(entity);
            result.put("success", ok);
            result.put("message", ok ? "更新成功" : "更新失败");
            if (ok) {
                result.put("data", this.getById(entity.getId()));
            }
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "更新异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    public Map<String, Object> deleteById(String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean ok = this.removeById(id);
            result.put("success", ok);
            result.put("message", ok ? "删除成功" : "删除失败");
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    public Map<String, Object> pageQuery(Integer current, Integer size, Long deptId, String deptName, Long parentDeptId) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (current == null || current < 1) {
                current = 1;
            }
            if (size == null || size < 1) {
                size = 10;
            }

            Page<QweiDepartment> page = new Page<>(current, size);
            LambdaQueryWrapper<QweiDepartment> q = new LambdaQueryWrapper<>();
            if (deptId != null) {
                q.eq(QweiDepartment::getDeptId, deptId);
            }
            if (deptName != null && !deptName.trim().isEmpty()) {
                q.like(QweiDepartment::getDeptName, deptName.trim());
            }
            if (parentDeptId != null) {
                q.eq(QweiDepartment::getParentDeptId, parentDeptId);
            }
            q.orderByAsc(QweiDepartment::getOrderNum).orderByDesc(QweiDepartment::getUpdatedAt);

            Page<QweiDepartment> data = this.page(page, q);
            result.put("success", true);
            result.put("message", "查询成功");
            result.put("data", data.getRecords());
            result.put("total", data.getTotal());
            result.put("current", data.getCurrent());
            result.put("size", data.getSize());
            result.put("pages", data.getPages());
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "查询异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> syncFromQiWei(String tenantIdParam) {
        Map<String, Object> result = new HashMap<>();
        try {
            QiWeiConfig cfg = loadQiWeiConfig();
            String tenantId = resolveTenantId(tenantIdParam);
            // 确保后续对 qwei_department 的查询/写入都带 tenant_id 条件
            TenantContextHolder.setTenantId(tenantId);
            String corpId = requireNonBlank(cfg.getCorpid(), "qiwei_config.corpid不能为空");
            String contactSecret = requireNonBlank(cfg.getContractSecret(), "qiwei_config.contractSecret不能为空");
            String appSecret = trimToNull(cfg.getAppSecret());

            List<QweiDepartment> remoteDepartments;
            try {
                String token = getAccessToken(corpId, contactSecret);
                remoteDepartments = fetchDepartments(token);
            } catch (Exception e) {
                String msg = e.getMessage();
                boolean contactForbidden = msg != null && (msg.contains("e=48009")
                        || msg.contains("api forbidden for contact assistant"));
                if (!contactForbidden || appSecret == null) {
                    throw e;
                }
                String appToken = getAccessToken(corpId, appSecret);
                remoteDepartments = fetchDepartments(appToken);
            }

            int inserted = 0;
            int updated = 0;
            for (QweiDepartment dept : remoteDepartments) {
                dept.setTenantId(tenantId);
                LambdaQueryWrapper<QweiDepartment> q = new LambdaQueryWrapper<QweiDepartment>()
                        .eq(QweiDepartment::getDeptId, dept.getDeptId());
                QweiDepartment exists = this.getOne(q, false);
                LocalDateTime now = LocalDateTime.now();
                if (exists == null) {
                    dept.setId(UUID.randomUUID().toString());
                    dept.setIsDeleted(0);
                    dept.setCreatedAt(now);
                    dept.setUpdatedAt(now);
                    try {
                        this.save(dept);
                        inserted++;
                    } catch (Exception insertEx) {
                        // 若数据库唯一索引仍是 dept_id 单列，且历史数据 tenant_id 为空，会导致不同租户插入时撞唯一键。
                        // 这里做一次“修复脏数据”：找到 dept_id 对应的旧记录，如果 tenant_id 为空则补齐为当前租户并更新。
                        if (!isDuplicateDeptId(insertEx)) {
                            throw insertEx;
                        }
                        QweiDepartment legacy = findByDeptIdIgnoreTenant(dept.getDeptId());
                        if (legacy == null) {
                            throw insertEx;
                        }
                        String legacyTenant = trimToNull(legacy.getTenantId());
                        if (legacyTenant == null) {
                            this.baseMapper.updateLegacyTenantAndFieldsByIdIgnoreTenant(
                                    legacy.getId(),
                                    tenantId,
                                    dept.getDeptName(),
                                    dept.getParentDeptId(),
                                    dept.getOrderNum(),
                                    0,
                                    now
                            );
                            updated++;
                        } else if (!tenantId.equals(legacyTenant)) {
                            throw new IllegalStateException("部门dept_id=" + dept.getDeptId()
                                    + " 已存在且属于其他租户(" + legacyTenant + ")。请把唯一索引改为(tenant_id, dept_id)。");
                        } else {
                            // 同租户但 exists 查不到（理论上不该发生），走更新
                            exists = legacy;
                            exists.setDeptName(dept.getDeptName());
                            exists.setParentDeptId(dept.getParentDeptId());
                            exists.setOrderNum(dept.getOrderNum());
                            exists.setIsDeleted(0);
                            exists.setUpdatedAt(now);
                            this.updateById(exists);
                            updated++;
                        }
                    }
                } else {
                    exists.setDeptName(dept.getDeptName());
                    exists.setParentDeptId(dept.getParentDeptId());
                    exists.setOrderNum(dept.getOrderNum());
                    exists.setIsDeleted(0);
                    exists.setUpdatedAt(now);
                    this.updateById(exists);
                    updated++;
                }
            }

            result.put("success", true);
            result.put("message", "同步成功");
            result.put("inserted", inserted);
            result.put("updated", updated);
            result.put("total", remoteDepartments.size());
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "同步异常：" + e.getMessage());
            return result;
        } finally {
            TenantContextHolder.clear();
        }
    }

    private QiWeiConfig loadQiWeiConfig() throws Exception {
        // 优先使用 JVM 参数，便于联调/脚本执行：
        // -Dqiwei.corpid=xxx -Dqiwei.contactSecret=xxx
        String corpid = trimToNull(System.getProperty("qiwei.corpid"));
        String contactSecret = trimToNull(System.getProperty("qiwei.contactSecret"));
        if (corpid != null && contactSecret != null) {
            QiWeiConfig cfg = new QiWeiConfig();
            cfg.setCorpid(corpid);
            cfg.setContractSecret(contactSecret);
            cfg.setAppSecret(trimToNull(System.getProperty("qiwei.appSecret")));
            return cfg;
        }

        String tenantId = System.getProperty("tenantId", "TENANT_ID_CST_2026");
        TenantContextHolder.setTenantId(tenantId);
        try {
            LambdaQueryWrapper<DictItem> q = new LambdaQueryWrapper<DictItem>()
                    .eq(DictItem::getName, DictItemConstants.QIWEI_CONFIG)
                    .orderByDesc(DictItem::getUpdatedTime)
                    .orderByDesc(DictItem::getCreatedTime)
                    .last("limit 1");
            DictItem item = dictItemMapper.selectOne(q);
            if (item == null || item.getValue() == null || item.getValue().trim().isEmpty()) {
                throw new IllegalStateException("未找到 qiwei_config");
            }
            String json = PasswordUtil.decryptReversibleWithDefaultSalt(item.getValue());
            return OBJECT_MAPPER.readValue(json, QiWeiConfig.class);
        } finally {
            TenantContextHolder.clear();
        }
    }

    private String getAccessToken(String corpId, String secret) throws Exception {
        String url = QiWeiApiConstants.GET_TOKEN + "?corpid="
                + URLEncoder.encode(corpId, StandardCharsets.UTF_8)
                + "&corpsecret=" + URLEncoder.encode(secret, StandardCharsets.UTF_8);
        HttpRequest request = HttpRequest.newBuilder(URI.create(url)).GET().build();
        String body = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString()).body();
        JsonNode json = OBJECT_MAPPER.readTree(body);
        int errCode = json.path("errcode").asInt(-1);
        if (errCode != 0) {
            throw new IllegalStateException("获取access_token失败: " + body);
        }
        return json.path("access_token").asText();
    }

    private List<QweiDepartment> fetchDepartments(String token) throws Exception {
        String url = QiWeiApiConstants.DEPARTMENT_LIST + "?access_token="
                + URLEncoder.encode(token, StandardCharsets.UTF_8);
        HttpRequest request = HttpRequest.newBuilder(URI.create(url)).GET().build();
        String body = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString()).body();
        JsonNode json = OBJECT_MAPPER.readTree(body);
        int errCode = json.path("errcode").asInt(-1);
        if (errCode != 0) {
            throw new IllegalStateException("获取部门列表失败: " + body);
        }

        List<QweiDepartment> list = new ArrayList<>();
        JsonNode departmentNode = json.path("department");
        if (departmentNode.isArray()) {
            for (JsonNode n : departmentNode) {
                QweiDepartment dept = new QweiDepartment();
                dept.setDeptId(n.path("id").asLong());
                dept.setDeptName(n.path("name").asText(null));
                dept.setParentDeptId(n.path("parentid").asLong());
                dept.setOrderNum(n.path("order").asInt(0));
                list.add(dept);
            }
        }
        return list;
    }

    private String requireNonBlank(String value, String msg) {
        if (value == null || value.trim().isEmpty()) {
            throw new IllegalStateException(msg);
        }
        return value.trim();
    }

    private boolean isDuplicateDeptId(Exception e) {
        String msg = e.getMessage();
        return msg != null && (msg.contains("Duplicate entry") && msg.contains("uk_qwei_department_dept_id"));
    }

    private QweiDepartment findByDeptIdIgnoreTenant(Long deptId) {
        return this.baseMapper.selectByDeptIdIgnoreTenant(deptId);
    }

    private String trimToNull(String value) {
        if (value == null) {
            return null;
        }
        String t = value.trim();
        return t.isEmpty() ? null : t;
    }

    private String resolveTenantId(String tenantIdFromEntity) {
        String current = trimToNull(TenantContextHolder.getTenantId());
        if (current != null) {
            return current;
        }
        String t = trimToNull(tenantIdFromEntity);
        if (t != null) {
            return t;
        }
        String fromProp = trimToNull(System.getProperty("tenantId"));
        if (fromProp != null) {
            return fromProp;
        }
        throw new IllegalStateException("tenantId不能为空（请设置租户上下文或传入 tenantId 或 -DtenantId）");
    }
}

