package com.zhentao.util;

import com.zhentao.entity.MatchData;

import java.util.*;

public class MatchingAlgorithmUtils {
    public static double calculateMatchScore(MatchData a, MatchData b) {
        if (a == null || b == null) return 0;
        double genderBonus = genderBonus(a.getGender(), b.getGender());
        double interest = jaccard(a.getInterests(), b.getInterests());
        double age = ageScore(a.getAge(), b.getAge());
        double loc = locationScore(a.getLatitude(), a.getLongitude(), b.getLatitude(), b.getLongitude());
        double base = Math.min(100, ((interest * 0.4 + age * 0.3 + loc * 0.2) / (0.4 + 0.3 + 0.2)) * 100);
        return Math.min(100, base * (1 + genderBonus));
    }

    private static double genderBonus(Integer g1, Integer g2) {
        if (g1 != null && g2 != null && !g1.equals(g2) && g1 < 2 && g2 < 2) return 0.2;
        return 0.0;
    }

    private static double jaccard(List<String> a, List<String> b) {
        if (a == null || b == null) return 0;
        if (a.isEmpty() && b.isEmpty()) return 0.5;
        Set<String> u = new HashSet<>(a); u.addAll(b);
        Set<String> i = new HashSet<>(a); i.retainAll(b);
        return u.isEmpty() ? 0 : (double) i.size() / u.size();
    }

    private static double ageScore(Integer i1, Integer i2) {
        if (i1 == null || i2 == null) return 0.5;
        int d = Math.abs(i1 - i2);
        if (d <= 0) return 1.0;
        if (d >= 20) return 0.1;
        return 1.0 - (d / 20.0 * 0.9);
    }

    private static double locationScore(Double la1, Double lo1, Double la2, Double lo2) {
        if (la1 == null || lo1 == null || la2 == null || lo2 == null) return 0.5;
        return locationScore(la1.doubleValue(), lo1.doubleValue(), la2.doubleValue(), lo2.doubleValue());
    }

    private static double locationScore(double la1, double lo1, double la2, double lo2) {
        double d = distance(la1, lo1, la2, lo2);
        if (d <= 0) return 1.0;
        if (d >= 100) return 0.0;
        return 1.0 - (d / 100.0);
    }

    private static double distance(double la1, double lo1, double la2, double lo2) {
        final int R = 6371;
        double dLat = Math.toRadians(la2 - la1);
        double dLon = Math.toRadians(lo2 - lo1);
        double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(la1)) * Math.cos(Math.toRadians(la2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        return R * c;
    }
}

