package com.njzscloud.dispose.cst.org.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity;
import com.njzscloud.dispose.cst.customer.pojo.result.CustomerResult;
import com.njzscloud.dispose.cst.customer.pojo.result.SearchCustomerResult;
import com.njzscloud.dispose.cst.org.constant.ApplyStatus;
import com.njzscloud.dispose.cst.org.constant.TransSortType;
import com.njzscloud.dispose.cst.org.mapper.OrgMapper;
import com.njzscloud.dispose.cst.org.pojo.entity.OrgApplyEntity;
import com.njzscloud.dispose.cst.org.pojo.entity.OrgEntity;
import com.njzscloud.dispose.cst.org.pojo.param.AddOrgParam;
import com.njzscloud.dispose.cst.org.pojo.param.OrgPagingParam;
import com.njzscloud.dispose.cst.org.pojo.result.OrgResult;
import com.njzscloud.dispose.cst.org.pojo.result.TransOrgStatistics;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 组织信息
 *
 * @author lzq
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrgService extends ServiceImpl<OrgMapper, OrgEntity> implements IService<OrgEntity> {
    private final OrgApplyService orgApplyService;

    /**
     * 新增
     */
    @Transactional(rollbackFor = Exception.class)
    public Long add(AddOrgParam addOrgParam) {
        String uscc = addOrgParam.getUscc();
        String orgName = addOrgParam.getOrgName();
        boolean exists = this.exists(Wrappers.lambdaQuery(OrgEntity.class)
            .eq(OrgEntity::getUscc, uscc)
            .or().eq(OrgEntity::getOrgName, orgName)
        );
        Assert.isFalse(exists, () -> Exceptions.exception("当前组织已存在，组织名称：{}，统一社会信用代码：{}", orgName, uscc));
        OrgEntity entity = BeanUtil.copyProperties(addOrgParam, OrgEntity.class);
        this.save(entity);
        return entity.getId();
    }

    /**
     * 修改
     */
    public void modify(OrgEntity orgEntity) {
        this.updateById(orgEntity);
    }

    /**
     * 删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        this.removeBatchByIds(ids);
    }

    /**
     * 详情
     */
    public OrgEntity detail(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     */
    public PageResult<OrgResult> paging(PageParam pageParam, OrgPagingParam orgPagingParam) {
        String keywords = orgPagingParam.getKeywords();
        IdentityCategory identityCategory = orgPagingParam.getIdentityCategory();
        QueryWrapper<OrgResult> ew = Wrappers.<OrgResult>query()
            .eq("o.deleted", Boolean.FALSE)
            .eq(identityCategory != null, "c.identity_category", identityCategory)
            .and(StrUtil.isNotBlank(keywords), it ->
                it.like("o.uscc", keywords)
                    .or().like("o.org_name", keywords)
                    .or().like("o.legal_representative", keywords)
            );
        PageResult<OrgResult> page = PageResult.of(baseMapper.paging(pageParam.toPage(), ew));
        List<OrgResult> records = page.getRecords();
        if (records.isEmpty()) {
            return page;
        }
        List<Long> orgIds = records.stream()
            .map(OrgResult::getId)
            .filter(Objects::nonNull)
            .toList();
        QueryWrapper<CustomerEntity> customerEw = Wrappers.<CustomerEntity>query()
            .eq("cc.deleted", Boolean.FALSE)
            .eq("cc.manager", Boolean.TRUE)
            .in("cc.org_id", orgIds);
        // 如果指定了身份类型，客户列表也需要过滤
        if (identityCategory != null) {
            customerEw.eq("cc.identity_category", identityCategory);
        }
        Map<Long, List<CustomerResult>> orgMap = baseMapper.queryList(customerEw)
            .stream()
            .collect(Collectors.groupingBy(CustomerResult::getOrgId));
        records.forEach(org -> org.setCustomerList(orgMap.get(org.getId())));
        return page;
    }

    /**
     * 运输方分页查询
     *
     * @param pageParam 分页参数
     * @param sortType  排序类型：time-按创建时间倒序、clearance-按清运数排序、evaluate-按综合评价倒序、distance-按距离正序
     * @param lng       经度（sortType=distance时必传）
     * @param lat       纬度（sortType=distance时必传）
     */
    public PageResult<OrgResult> transOrgPaging(PageParam pageParam, String sortType, Double lng, Double lat) {
        // 默认按创建时间倒序
        if (StrUtil.isBlank(sortType)) {
            sortType = TransSortType.TIME.getVal();
        }
        QueryWrapper<OrgResult> ew = Wrappers.<OrgResult>query()
            .eq("o.deleted", Boolean.FALSE)
            .eq("c.identity_category", IdentityCategory.YunShu);
        // 根据排序类型添加排序条件
        if (TransSortType.TIME.getVal().equals(sortType)) {
            ew.orderByDesc("o.create_time");
        }
        PageResult<OrgResult> page = PageResult.of(baseMapper.paging(pageParam.toPage(), ew));
        List<OrgResult> records = page.getRecords();
        if (records.isEmpty()) {
            return page;
        }
        List<Long> orgIds = records.stream()
            .map(OrgResult::getId)
            .filter(Objects::nonNull)
            .toList();
        QueryWrapper<CustomerEntity> customerEw = Wrappers.<CustomerEntity>query()
            .eq("cc.deleted", Boolean.FALSE)
            .eq("cc.manager", Boolean.TRUE)
            .in("cc.org_id", orgIds);
        customerEw.eq("cc.identity_category", IdentityCategory.YunShu);
        Map<Long, List<CustomerResult>> orgMap = baseMapper.queryList(customerEw)
            .stream()
            .collect(Collectors.groupingBy(CustomerResult::getOrgId));
        records.forEach(org -> org.setCustomerList(orgMap.get(org.getId())));
        // 查询统计数据并计算排名
        setTransOrgStatistics(records, orgIds);
        // 根据排序类型进行排序
        sortRecords(records, sortType, lng, lat);
        return page;
    }

    /**
     * 根据排序类型对记录进行排序
     */
    private void sortRecords(List<OrgResult> records, String sortType, Double userLng, Double userLat) {
        if (TransSortType.CLEARANCE.getVal().equals(sortType)) {
            // 按清运数排序（降序）
            records.sort((a, b) -> {
                Integer clearanceA = b.getClearanceRank() != null ? b.getClearanceRank() : 0;
                Integer clearanceB = a.getClearanceRank() != null ? a.getClearanceRank() : 0;
                return clearanceA.compareTo(clearanceB);
            });
        } else if (TransSortType.EVALUATE.getVal().equals(sortType)) {
            // 按综合评价倒序
            records.sort((a, b) -> {
                BigDecimal scoreA = b.getOverallScore() != null ? b.getOverallScore() : BigDecimal.ZERO;
                BigDecimal scoreB = a.getOverallScore() != null ? a.getOverallScore() : BigDecimal.ZERO;
                return scoreA.compareTo(scoreB);
            });
        } else if (TransSortType.DISTANCE.getVal().equals(sortType) && userLng != null && userLat != null) {
            // 按距离正序（计算直线距离）
            records.sort((a, b) -> {
                Double distanceA = calculateDistance(userLng, userLat,
                    a.getLng() != null ? a.getLng() : 0.0,
                    a.getLat() != null ? a.getLat() : 0.0);
                Double distanceB = calculateDistance(userLng, userLat,
                    b.getLng() != null ? b.getLng() : 0.0,
                    b.getLat() != null ? b.getLat() : 0.0);
                return distanceA.compareTo(distanceB);
            });
        }
        // time 排序已在 SQL 中处理，无需额外排序
    }

    /**
     * 计算两个经纬度之间的直线距离（单位：公里）
     * 使用 Haversine 公式
     */
    private double calculateDistance(double lng1, double lat1, double lng2, double lat2) {
        final double R = 6371; // 地球半径（公里）
        double latDistance = Math.toRadians(lat2 - lat1);
        double lngDistance = Math.toRadians(lng2 - lng1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
            + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
            * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return Math.round(R * c * 1000) / 1000.0; // 返回公里，保留3位小数
    }

    /**
     * 设置运输方统计数据和排名
     */
    private void setTransOrgStatistics(List<OrgResult> records, List<Long> orgIds) {
        // 查询所有运输方的统计数据
        List<TransOrgStatistics> statisticsList = baseMapper.queryTransOrgStatistics(orgIds);
        if (statisticsList.isEmpty()) {
            return;
        }
        Map<Long, TransOrgStatistics> statisticsMap = statisticsList.stream()
            .collect(Collectors.toMap(TransOrgStatistics::getOrgId, s -> s, (a, b) -> a));
        // 计算订单数量排名（降序，数量多的排名靠前）
        List<TransOrgStatistics> orderRankedList = statisticsList.stream()
            .sorted(Comparator.comparingInt((TransOrgStatistics s) -> s.getOrderCount() == null ? 0 : s.getOrderCount()).reversed())
            .toList();
        Map<Long, Integer> orderRankMap = new java.util.HashMap<>();
        int orderRank = 1;
        Integer prevOrderCount = null;
        for (TransOrgStatistics stat : orderRankedList) {
            Integer count = stat.getOrderCount() == null ? 0 : stat.getOrderCount();
            if (prevOrderCount != null && !count.equals(prevOrderCount)) {
                orderRank = orderRankMap.size() + 1;
            }
            orderRankMap.put(stat.getOrgId(), orderRank);
            prevOrderCount = count;
        }
        // 计算清运数量排名（降序，数量多的排名靠前）
        List<TransOrgStatistics> clearanceRankedList = statisticsList.stream()
            .sorted(Comparator.comparingInt((TransOrgStatistics s) -> s.getClearanceCount() == null ? 0 : s.getClearanceCount()).reversed())
            .toList();
        Map<Long, Integer> clearanceRankMap = new java.util.HashMap<>();
        int clearanceRank = 1;
        Integer prevClearanceCount = null;
        for (TransOrgStatistics stat : clearanceRankedList) {
            Integer count = stat.getClearanceCount() == null ? 0 : stat.getClearanceCount();
            if (prevClearanceCount != null && !count.equals(prevClearanceCount)) {
                clearanceRank = clearanceRankMap.size() + 1;
            }
            clearanceRankMap.put(stat.getOrgId(), clearanceRank);
            prevClearanceCount = count;
        }
        // 设置到OrgResult中
        records.forEach(org -> {
            TransOrgStatistics stat = statisticsMap.get(org.getId());
            if (stat != null) {
                org.setOrderRank(orderRankMap.get(org.getId()));
                org.setClearanceRank(clearanceRankMap.get(org.getId()));
                org.setOverallScore(stat.getOverallScore());
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    public void apply(Long customerId, Long orgId) {
        SearchCustomerResult customerResult = baseMapper.getCustomer(customerId);
        Assert.isFalse(customerResult.getManager(), () -> Exceptions.exception("企业/组织管理员不能加入其他公司"));
        Assert.isNull(customerResult.getOrgId(), () -> Exceptions.exception("已加入其他企业/组织请先退出"));
        boolean exists = orgApplyService.exists(Wrappers.lambdaQuery(OrgApplyEntity.class)
            .in(OrgApplyEntity::getApplyStatus, ApplyStatus.ShenQingZhong, ApplyStatus.TongYi)
            .eq(OrgApplyEntity::getCustomerId, customerId)
            .eq(OrgApplyEntity::getOrgId, orgId)
        );
        Assert.isFalse(exists, () -> Exceptions.exception("已向组织发起申请，无需重复提交"));
        orgApplyService.add(new OrgApplyEntity()
            .setApplyStatus(ApplyStatus.ShenQingZhong)
            .setApplyTime(LocalDateTime.now())
            .setCustomerId(customerId)
            .setOrgId(orgId)
        );
    }

    @Transactional(rollbackFor = Exception.class)
    public void quit(Long customerId) {
        boolean result = baseMapper.quitOrg(customerId);
        Assert.isTrue(result, () -> Exceptions.exception("未加入企业，无需操作"));
    }

    @Transactional(rollbackFor = Exception.class)
    public void agree(Long id, boolean isAgree, String cause) {
        OrgApplyEntity applyInfo = orgApplyService.getById(id);
        Assert.notNull(applyInfo, () -> Exceptions.exception("未查询到申请信息"));
        ApplyStatus oldApplyStatus = applyInfo.getApplyStatus();
        Assert.isTrue(oldApplyStatus == ApplyStatus.ShenQingZhong, () -> Exceptions.exception("{}的申请，无需操作", oldApplyStatus.getTxt()));
        ApplyStatus applyStatus;
        if (isAgree) {
            Long customerId = applyInfo.getCustomerId();
            Long orgId = applyInfo.getOrgId();
            boolean result = baseMapper.admitCustomer(orgId, customerId);
            Assert.isTrue(result, () -> Exceptions.exception("当前客户未退出原有的组织"));
            applyStatus = ApplyStatus.TongYi;
        } else {
            applyStatus = ApplyStatus.JuJue;
        }
        orgApplyService.updateById(new OrgApplyEntity()
            .setId(id)
            .setApplyStatus(applyStatus)
            .setCause(cause)
        );
    }
}
