package org.github.tess1o.geopulse.insight.service.badge;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import org.github.tess1o.geopulse.insight.model.Badge;
import org.github.tess1o.geopulse.shared.service.TimestampUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.UUID;

@ApplicationScoped
public class FirstMonthBadgeCalculator implements BadgeCalculator {

    private final EntityManager entityManager;

    public FirstMonthBadgeCalculator(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public String getBadgeId() {
        return "first_month";
    }

    @Override
    public Badge calculateBadge(UUID userId) {
        int[] trackingData = getTrackingDays(userId);
        int trackedDays = trackingData[0];
        boolean firstMonthComplete = trackedDays >= 30;

        return new Badge(
                getBadgeId(),
                "First Month Complete!",
                "Successfully tracked for 30 days",
                "🎉",
                firstMonthComplete,
                firstMonthComplete ? getTrackingStartDate(userId) : null,
                null, null, null
        );
    }

    private int[] getTrackingDays(UUID userId) {
        String firstDateSql = """
                SELECT MIN(DATE(timestamp AT TIME ZONE 'UTC'))
                FROM gps_points
                WHERE user_id = :userId
                """;

        Query firstDateQuery = entityManager.createNativeQuery(firstDateSql);
        firstDateQuery.setParameter("userId", userId);

        LocalDate firstDate = (LocalDate) firstDateQuery.getSingleResult();
        if (firstDate == null) {
            return new int[]{0, 0};
        }

        LocalDate today = LocalDate.now();
        int totalDays = (int) ChronoUnit.DAYS.between(firstDate, today) + 1;

        String trackedDaysSql = """
                SELECT COUNT(DISTINCT DATE(timestamp AT TIME ZONE 'UTC'))
                FROM gps_points
                WHERE user_id = :userId
                """;

        Query trackedDaysQuery = entityManager.createNativeQuery(trackedDaysSql);
        trackedDaysQuery.setParameter("userId", userId);

        Number result = (Number) trackedDaysQuery.getSingleResult();
        int trackedDays = result != null ? result.intValue() : 0;

        return new int[]{trackedDays, totalDays};
    }

    private String getTrackingStartDate(UUID userId) {
        String sql = """
                SELECT MIN(timestamp)
                FROM gps_points
                WHERE user_id = :userId
                """;

        Query query = entityManager.createNativeQuery(sql);
        query.setParameter("userId", userId);

        Object result = query.getSingleResult();
        var startInstant = TimestampUtils.getInstantSafe(result);
        if (startInstant == null) {
            return "No tracking data";
        }

        LocalDate startDate = startInstant.atZone(ZoneOffset.UTC).toLocalDate();
        return startDate.format(DateTimeFormatter.ofPattern("MMMM d, yyyy"));
    }
}
