package com.honey.honey.controller;

import com.honey.honey.model.Payment;
import com.honey.honey.model.Payout;
import com.honey.honey.model.UserA;
import com.honey.honey.repository.PaymentRepository;
import com.honey.honey.repository.PayoutRepository;
import com.honey.honey.repository.UserARepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/admin/dashboard")
@RequiredArgsConstructor
@PreAuthorize("hasRole('ADMIN')")
public class AdminDashboardController {

    private final UserARepository userARepository;
    private final PaymentRepository paymentRepository;
    private final PayoutRepository payoutRepository;

    @GetMapping("/stats")
    public ResponseEntity<Map<String, Object>> getDashboardStats() {
        Instant now = Instant.now();
        Instant todayStart = now.truncatedTo(ChronoUnit.DAYS);
        Instant weekStart = now.minus(7, ChronoUnit.DAYS);
        Instant monthStart = now.minus(30, ChronoUnit.DAYS);
        Instant dayAgo = now.minus(24, ChronoUnit.HOURS);
        Instant weekAgo = now.minus(7, ChronoUnit.DAYS);
        Instant monthAgo = now.minus(30, ChronoUnit.DAYS);
        
        // Convert to Unix timestamps (seconds) for UserA date fields
        int todayStartTs = (int) todayStart.getEpochSecond();
        int weekStartTs = (int) weekStart.getEpochSecond();
        int monthStartTs = (int) monthStart.getEpochSecond();
        int dayAgoTs = (int) dayAgo.getEpochSecond();
        int weekAgoTs = (int) weekAgo.getEpochSecond();
        int monthAgoTs = (int) monthAgo.getEpochSecond();

        Map<String, Object> stats = new HashMap<>();

        // Total Users
        long totalUsers = userARepository.count();
        long newUsersToday = userARepository.countByDateRegAfter(todayStartTs);
        long newUsersWeek = userARepository.countByDateRegAfter(weekStartTs);
        long newUsersMonth = userARepository.countByDateRegAfter(monthStartTs);

        // Active Players (users who logged in recently)
        long activePlayers24h = userARepository.countByDateLoginAfter(dayAgoTs);
        long activePlayers7d = userARepository.countByDateLoginAfter(weekAgoTs);
        long activePlayers30d = userARepository.countByDateLoginAfter(monthAgoTs);

        // Revenue (from completed payments) - in Stars
        int totalRevenue = paymentRepository.sumStarsAmountByStatus(Payment.PaymentStatus.COMPLETED)
                .orElse(0);
        int revenueToday = paymentRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payment.PaymentStatus.COMPLETED, todayStart).orElse(0);
        int revenueWeek = paymentRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payment.PaymentStatus.COMPLETED, weekStart).orElse(0);
        int revenueMonth = paymentRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payment.PaymentStatus.COMPLETED, monthStart).orElse(0);

        // Payouts (from completed payouts) - in Stars
        int totalPayouts = payoutRepository.sumStarsAmountByStatus(Payout.PayoutStatus.COMPLETED)
                .orElse(0);
        int payoutsToday = payoutRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payout.PayoutStatus.COMPLETED, todayStart).orElse(0);
        int payoutsWeek = payoutRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payout.PayoutStatus.COMPLETED, weekStart).orElse(0);
        int payoutsMonth = payoutRepository.sumStarsAmountByStatusAndCreatedAtAfter(
                Payout.PayoutStatus.COMPLETED, monthStart).orElse(0);

        // Net Revenue (in Stars)
        int netRevenue = totalRevenue - totalPayouts;
        int netRevenueToday = revenueToday - payoutsToday;
        int netRevenueWeek = revenueWeek - payoutsWeek;
        int netRevenueMonth = revenueMonth - payoutsMonth;

        // CRYPTO only: revenue and payouts in USD (for dashboard / financial analytics)
        BigDecimal cryptoRevenueTotal = paymentRepository.sumUsdAmountByStatusAndUsdAmountNotNull(Payment.PaymentStatus.COMPLETED).orElse(BigDecimal.ZERO);
        BigDecimal cryptoRevenueToday = paymentRepository.sumUsdAmountByStatusAndUsdAmountNotNullAndCreatedAtAfter(Payment.PaymentStatus.COMPLETED, todayStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoRevenueWeek = paymentRepository.sumUsdAmountByStatusAndUsdAmountNotNullAndCreatedAtAfter(Payment.PaymentStatus.COMPLETED, weekStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoRevenueMonth = paymentRepository.sumUsdAmountByStatusAndUsdAmountNotNullAndCreatedAtAfter(Payment.PaymentStatus.COMPLETED, monthStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoPayoutsTotal = payoutRepository.sumUsdAmountByTypeCryptoAndStatus(Payout.PayoutStatus.COMPLETED).orElse(BigDecimal.ZERO);
        BigDecimal cryptoPayoutsToday = payoutRepository.sumUsdAmountByTypeCryptoAndStatusAndCreatedAtAfter(Payout.PayoutStatus.COMPLETED, todayStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoPayoutsWeek = payoutRepository.sumUsdAmountByTypeCryptoAndStatusAndCreatedAtAfter(Payout.PayoutStatus.COMPLETED, weekStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoPayoutsMonth = payoutRepository.sumUsdAmountByTypeCryptoAndStatusAndCreatedAtAfter(Payout.PayoutStatus.COMPLETED, monthStart).orElse(BigDecimal.ZERO);
        BigDecimal cryptoNetRevenueTotal = cryptoRevenueTotal.subtract(cryptoPayoutsTotal);
        BigDecimal cryptoNetRevenueToday = cryptoRevenueToday.subtract(cryptoPayoutsToday);
        BigDecimal cryptoNetRevenueWeek = cryptoRevenueWeek.subtract(cryptoPayoutsWeek);
        BigDecimal cryptoNetRevenueMonth = cryptoRevenueMonth.subtract(cryptoPayoutsMonth);

        // Build response
        stats.put("users", Map.of(
                "total", totalUsers,
                "newToday", newUsersToday,
                "newWeek", newUsersWeek,
                "newMonth", newUsersMonth
        ));

        stats.put("activePlayers", Map.of(
                "last24h", activePlayers24h,
                "last7d", activePlayers7d,
                "last30d", activePlayers30d
        ));

        stats.put("revenue", Map.of(
                "total", totalRevenue,
                "today", revenueToday,
                "week", revenueWeek,
                "month", revenueMonth
        ));

        stats.put("payouts", Map.of(
                "total", totalPayouts,
                "today", payoutsToday,
                "week", payoutsWeek,
                "month", payoutsMonth
        ));

        stats.put("netRevenue", Map.of(
                "total", netRevenue,
                "today", netRevenueToday,
                "week", netRevenueWeek,
                "month", netRevenueMonth
        ));

        Map<String, Object> crypto = new HashMap<>();
        crypto.put("revenueUsd", cryptoRevenueTotal);
        crypto.put("revenueUsdToday", cryptoRevenueToday);
        crypto.put("revenueUsdWeek", cryptoRevenueWeek);
        crypto.put("revenueUsdMonth", cryptoRevenueMonth);
        crypto.put("payoutsUsd", cryptoPayoutsTotal);
        crypto.put("payoutsUsdToday", cryptoPayoutsToday);
        crypto.put("payoutsUsdWeek", cryptoPayoutsWeek);
        crypto.put("payoutsUsdMonth", cryptoPayoutsMonth);
        crypto.put("profitUsd", cryptoNetRevenueTotal);
        crypto.put("profitUsdToday", cryptoNetRevenueToday);
        crypto.put("profitUsdWeek", cryptoNetRevenueWeek);
        crypto.put("profitUsdMonth", cryptoNetRevenueMonth);
        stats.put("crypto", crypto);

        return ResponseEntity.ok(stats);
    }
}

