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.rj.entity.LbDailyUserTrade;
import com.rj.entity.LbDepartmentUser;
import com.rj.entity.LbPurchaseApply;
import com.rj.mapper.LbDailyUserTradeMapper;
import com.rj.mapper.LbDepartmentUserMapper;
import com.rj.mapper.LbPurchaseApplyMapper;
import com.rj.service.ILbDepartmentUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@Service
public class LbDepartmentUserServiceImpl extends ServiceImpl<LbDepartmentUserMapper, LbDepartmentUser>
        implements ILbDepartmentUserService {

    private static final int PURCHASE_APPLY_BATCH_SIZE = 200;

    @Autowired
    private LbDailyUserTradeMapper lbDailyUserTradeMapper;
    @Autowired
    private LbPurchaseApplyMapper lbPurchaseApplyMapper;

    @Override
    public Map<String, Object> add(LbDepartmentUser entity) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (entity.getUserId() == null || entity.getUserId().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "userId不能为空");
                return result;
            }
            if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "tenantId不能为空");
                return result;
            }
            if (entity.getName() == null || entity.getName().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "name不能为空");
                return result;
            }

            if (entity.getId() == null || entity.getId().trim().isEmpty()) {
                entity.setId(UUID.randomUUID().toString());
            }
            LocalDateTime now = LocalDateTime.now();
            entity.setCreateTime(now);
            entity.setUpdateTime(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(LbDepartmentUser 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.setUpdateTime(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,
                                         String tenantId,
                                         String userId,
                                         String parentId,
                                         String name,
                                         String phone,
                                         String industry) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (current == null || current < 1) {
                current = 1;
            }
            if (size == null || size < 1) {
                size = 10;
            }

            LambdaQueryWrapper<LbDepartmentUser> queryWrapper = new LambdaQueryWrapper<>();
            if (tenantId != null && !tenantId.trim().isEmpty()) {
                queryWrapper.eq(LbDepartmentUser::getTenantId, tenantId.trim());
            }
            if (userId != null && !userId.trim().isEmpty()) {
                queryWrapper.eq(LbDepartmentUser::getUserId, userId.trim());
            }
            if (parentId != null && !parentId.trim().isEmpty()) {
                queryWrapper.eq(LbDepartmentUser::getParentId, parentId.trim());
            }
            if (name != null && !name.trim().isEmpty()) {
                queryWrapper.like(LbDepartmentUser::getName, name.trim());
            }
            if (phone != null && !phone.trim().isEmpty()) {
                queryWrapper.like(LbDepartmentUser::getPhone, phone.trim());
            }
            if (industry != null && !industry.trim().isEmpty()) {
                queryWrapper.like(LbDepartmentUser::getIndustry, industry.trim());
            }
            queryWrapper.orderByDesc(LbDepartmentUser::getUpdateTime)
                    .orderByDesc(LbDepartmentUser::getCreateTime);

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

    @Override
    public Map<String, Object> bindParentUser(String parentUserId,
                                              String parentUserName,
                                              String childUserId,
                                              String childUserName,
                                              String tenantId) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (parentUserId == null || parentUserId.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "父用户id不能为空");
                return result;
            }
            if (childUserId == null || childUserId.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "子用户id不能为空");
                return result;
            }
            if (tenantId == null || tenantId.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "租户id不能为空");
                return result;
            }

            String parentUserIdTrim = parentUserId.trim();
            String childUserIdTrim = childUserId.trim();
            String tenantIdTrim = tenantId.trim();

            // 第1步：根据子用户id查询目标记录
            LambdaQueryWrapper<LbDepartmentUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LbDepartmentUser::getTenantId, tenantIdTrim)
                    .eq(LbDepartmentUser::getUserId, childUserIdTrim);
            if (childUserName != null && !childUserName.trim().isEmpty()) {
                queryWrapper.eq(LbDepartmentUser::getName, childUserName.trim());
            }
            LbDepartmentUser childUser = this.getOne(queryWrapper, false);
            if (childUser == null) {
                result.put("success", false);
                result.put("message", "未查询到对应子用户");
                return result;
            }

            // 第2步：设置父用户id
            childUser.setParentId(parentUserIdTrim);
            if (parentUserName != null && !parentUserName.trim().isEmpty()) {
                childUser.setParentName(parentUserName.trim());
            }
            childUser.setUpdateTime(LocalDateTime.now());

            // 第3步：更新数据库表
            boolean ok = this.updateById(childUser);
            result.put("success", ok);
            result.put("message", ok ? "绑定父用户成功" : "绑定父用户失败");
            if (ok) {
                Map<String, Object> data = new HashMap<>();
                data.put("parentUserId", parentUserIdTrim);
                data.put("parentUserName", parentUserName);
                data.put("childUserId", childUserIdTrim);
                data.put("childUserName", childUser.getName());
                data.put("tenantId", tenantIdTrim);
                data.put("record", this.getById(childUser.getId()));
                result.put("data", data);
            }
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "绑定父子用户异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    public Map<String, Object> syncFromDailyUserTrade(LocalDate startDate, LocalDate endDate) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (startDate == null || endDate == null) {
                result.put("success", false);
                result.put("message", "开始日期和结束日期不能为空");
                return result;
            }
            if (startDate.isAfter(endDate)) {
                result.put("success", false);
                result.put("message", "开始日期不能大于结束日期");
                return result;
            }

            List<LbDailyUserTrade> tradeList = lbDailyUserTradeMapper.selectList(
                    new LambdaQueryWrapper<LbDailyUserTrade>()
                            .ge(LbDailyUserTrade::getReportDate, startDate)
                            .le(LbDailyUserTrade::getReportDate, endDate)
                            .ge(LbDailyUserTrade::getDailyBuyAmt, 1)
                            .isNotNull(LbDailyUserTrade::getNickname)
                            .orderByDesc(LbDailyUserTrade::getUpdatedAt)
                            .orderByDesc(LbDailyUserTrade::getCreatedAt)
            );
            if (tradeList == null || tradeList.isEmpty()) {
                result.put("success", true);
                result.put("message", "无可同步数据");
                result.put("insertedCount", 0);
                result.put("skippedCount", 0);
                result.put("sourceCount", 0);
                result.put("startDate", startDate);
                result.put("endDate", endDate);
                return result;
            }

            List<LbDepartmentUser> existedUsers = this.list();
            Map<String, LbDepartmentUser> existingUserMap = new HashMap<>();
            for (LbDepartmentUser user : existedUsers) {
                if (user.getName() != null && !user.getName().trim().isEmpty()) {
                    existingUserMap.put(user.getName().trim(), user);
                }
            }

            Map<String, LbDailyUserTrade> latestTradeByNickname = new HashMap<>();
            List<LbDepartmentUser> toInsert = new ArrayList<>();
            List<LbDepartmentUser> toUpdate = new ArrayList<>();
            int skippedCount = 0;
            LocalDateTime now = LocalDateTime.now();
            Set<String> candidateNicknameSet = new HashSet<>();
            for (LbDailyUserTrade trade : tradeList) {
                String nickname = trade.getNickname() == null ? null : trade.getNickname().trim();
                if (nickname == null || nickname.isEmpty()) {
                    skippedCount++;
                    continue;
                }
                candidateNicknameSet.add(nickname);
                // tradeList 已按更新时间倒序，首次写入即最新数据
                latestTradeByNickname.putIfAbsent(nickname, trade);
            }

            Map<String, LbPurchaseApply> phoneMap = buildPurchaseApplyPhoneMap(candidateNicknameSet);
            for (Map.Entry<String, LbDailyUserTrade> entry : latestTradeByNickname.entrySet()) {
                String nickname = entry.getKey();
                LbDailyUserTrade trade = entry.getValue();
                LbDepartmentUser entity = existingUserMap.get(nickname);
                boolean isInsert = false;
                if (entity == null) {
                    entity = new LbDepartmentUser();
                    entity.setId(UUID.randomUUID().toString());
                    entity.setCreateTime(now);
                    isInsert = true;
                }
                entity.setTenantId(trade.getTenantId());
                entity.setUserId(trade.getUserId());
                entity.setName(nickname);
                entity.setParentId(trade.getPromoterId());
                entity.setParentName(trade.getPromoterName());

                LbPurchaseApply purchaseApply = phoneMap.get(buildPhoneKey(trade.getTenantId(), nickname));
                if (purchaseApply != null && purchaseApply.getApplyPhone() != null) {
                    String phone = purchaseApply.getApplyPhone().trim();
                    entity.setPhone(phone.isEmpty() ? null : phone);
                    entity.setJoinDate(purchaseApply.getApplyDate());
                }
                entity.setUpdateTime(now);
                if (isInsert) {
                    toInsert.add(entity);
                } else {
                    toUpdate.add(entity);
                }
            }

            if (!toInsert.isEmpty()) {
                this.saveBatch(toInsert);
            }
            if (!toUpdate.isEmpty()) {
                this.updateBatchById(toUpdate);
            }

            result.put("success", true);
            result.put("message", "同步完成");
            result.put("insertedCount", toInsert.size());
            result.put("updatedCount", toUpdate.size());
            result.put("skippedCount", skippedCount);
            result.put("sourceCount", tradeList.size());
            result.put("startDate", startDate);
            result.put("endDate", endDate);
            return result;
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "同步异常：" + e.getMessage());
            return result;
        }
    }

    private Map<String, LbPurchaseApply> buildPurchaseApplyPhoneMap(Set<String> applyUserSet) {
        Map<String, LbPurchaseApply> phoneMap = new HashMap<>();
        if (applyUserSet == null || applyUserSet.isEmpty()) {
            return phoneMap;
        }

        List<String> applyUserList = new ArrayList<>(applyUserSet);
        for (int i = 0; i < applyUserList.size(); i += PURCHASE_APPLY_BATCH_SIZE) {
            int end = Math.min(i + PURCHASE_APPLY_BATCH_SIZE, applyUserList.size());
            List<String> batchUsers = applyUserList.subList(i, end);

            List<LbPurchaseApply> purchaseApplyList = lbPurchaseApplyMapper.selectList(
                    new LambdaQueryWrapper<LbPurchaseApply>()
                            .in(LbPurchaseApply::getApplyUser, batchUsers)
                            .isNotNull(LbPurchaseApply::getApplyPhone)
                            .orderByDesc(LbPurchaseApply::getUpdateTime)
                            .orderByDesc(LbPurchaseApply::getCreateTime)
            );
            for (LbPurchaseApply item : purchaseApplyList) {
                if (item.getApplyUser() == null || item.getApplyPhone() == null) {
                    continue;
                }
                String applyUser = item.getApplyUser().trim();
                String phone = item.getApplyPhone().trim();
                if (applyUser.isEmpty() || phone.isEmpty()) {
                    continue;
                }
                String key = buildPhoneKey(item.getTenantId(), applyUser);
                // 已按更新时间倒序，首次写入即最新手机号
                phoneMap.putIfAbsent(key, item);
            }
        }
        return phoneMap;
    }

    private String buildPhoneKey(String tenantId, String applyUser) {
        String tenantPart = tenantId == null ? "" : tenantId.trim();
        String userPart = applyUser == null ? "" : applyUser.trim();
        return tenantPart + "#" + userPart;
    }
}
