using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RR3CommunityServer.Data;
using RR3CommunityServer.Services;
using static RR3CommunityServer.Data.RR3DbContext;

namespace RR3CommunityServer.Controllers;

[ApiController]
[Route("synergy/[controller]")]
public class RewardsController : ControllerBase
{
    private readonly RR3DbContext _context;
    private readonly ILogger<RewardsController> _logger;

    public RewardsController(RR3DbContext context, ILogger<RewardsController> logger)
    {
        _context = context;
        _logger = logger;
    }

    /// <summary>
    /// Get daily reward status for a user
    /// </summary>
    [HttpGet("daily/{synergyId}")]
    public async Task<IActionResult> GetDailyReward(string synergyId)
    {
        _logger.LogInformation("Getting daily reward for {SynergyId}", synergyId);

        var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == synergyId);
        if (user == null)
        {
            return NotFound(new { error = "User not found" });
        }

        var today = DateTime.UtcNow.Date;
        var reward = await _context.DailyRewards
            .FirstOrDefaultAsync(r => r.UserId == user.Id && r.RewardDate.Date == today);

        if (reward == null)
        {
            // Create new daily reward
            reward = new DailyReward
            {
                UserId = user.Id,
                RewardDate = DateTime.UtcNow,
                GoldAmount = 50, // Daily gold reward
                CashAmount = 5000, // Daily cash reward
                Claimed = false,
                Streak = await CalculateStreak(user.Id)
            };

            _context.DailyRewards.Add(reward);
            await _context.SaveChangesAsync();
        }

        return Ok(new
        {
            available = !reward.Claimed,
            gold = reward.GoldAmount,
            cash = reward.CashAmount,
            streak = reward.Streak,
            nextRewardIn = reward.Claimed ? (24 - (DateTime.UtcNow - reward.RewardDate).TotalHours) : 0
        });
    }

    /// <summary>
    /// Claim daily reward
    /// </summary>
    [HttpPost("daily/{synergyId}/claim")]
    public async Task<IActionResult> ClaimDailyReward(string synergyId)
    {
        _logger.LogInformation("Claiming daily reward for {SynergyId}", synergyId);

        var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == synergyId);
        if (user == null)
        {
            return NotFound(new { error = "User not found" });
        }

        var today = DateTime.UtcNow.Date;
        var reward = await _context.DailyRewards
            .FirstOrDefaultAsync(r => r.UserId == user.Id && r.RewardDate.Date == today);

        if (reward == null || reward.Claimed)
        {
            return BadRequest(new { error = "No reward available to claim" });
        }

        // Mark as claimed
        reward.Claimed = true;
        reward.ClaimedAt = DateTime.UtcNow;

        // Update user's gold and cash
        if (user.Gold == null) user.Gold = 0;
        if (user.Cash == null) user.Cash = 0;

        user.Gold += reward.GoldAmount;
        user.Cash += reward.CashAmount;

        await _context.SaveChangesAsync();

        return Ok(new
        {
            success = true,
            goldEarned = reward.GoldAmount,
            cashEarned = reward.CashAmount,
            totalGold = user.Gold,
            totalCash = user.Cash,
            streak = reward.Streak
        });
    }

    /// <summary>
    /// Purchase gold with real money (free in community server)
    /// </summary>
    [HttpPost("gold/purchase")]
    public async Task<IActionResult> PurchaseGold([FromBody] GoldPurchaseRequest request)
    {
        _logger.LogInformation("Processing gold purchase for {SynergyId}: {Amount} gold", 
            request.SynergyId, request.GoldAmount);

        var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == request.SynergyId);
        if (user == null)
        {
            return NotFound(new { error = "User not found" });
        }

        // In community server, all gold purchases are FREE!
        if (user.Gold == null) user.Gold = 0;
        user.Gold += request.GoldAmount;

        // Log the purchase
        var purchase = new Purchase
        {
            SynergyId = request.SynergyId,
            UserId = user.Id,
            ItemId = $"gold_{request.GoldAmount}",
            Sku = request.Sku ?? $"com.ea.rr3.gold_{request.GoldAmount}",
            OrderId = Guid.NewGuid().ToString(),
            PurchaseTime = DateTime.UtcNow,
            Token = Guid.NewGuid().ToString(),
            Price = 0, // FREE in community server
            Status = "approved"
        };

        _context.Purchases.Add(purchase);
        await _context.SaveChangesAsync();

        return Ok(new
        {
            success = true,
            goldPurchased = request.GoldAmount,
            totalGold = user.Gold,
            orderId = purchase.OrderId,
            message = "Gold added to your account (FREE in community server!)"
        });
    }

    /// <summary>
    /// Get time trial events
    /// </summary>
    [HttpGet("timetrials")]
    public async Task<IActionResult> GetTimeTrials()
    {
        _logger.LogInformation("Getting time trial events");

        var trials = await _context.TimeTrials
            .Where(t => t.Active)
            .OrderBy(t => t.StartDate)
            .ToListAsync();

        return Ok(new
        {
            events = trials.Select(t => new
            {
                id = t.Id,
                name = t.Name,
                track = t.TrackName,
                car = t.CarName,
                startDate = t.StartDate,
                endDate = t.EndDate,
                goldReward = t.GoldReward,
                cashReward = t.CashReward,
                targetTime = t.TargetTime
            })
        });
    }

    /// <summary>
    /// Submit time trial result
    /// </summary>
    [HttpPost("timetrials/{trialId}/submit")]
    public async Task<IActionResult> SubmitTimeTrial(int trialId, [FromBody] TimeTrialSubmission submission)
    {
        _logger.LogInformation("Submitting time trial {TrialId} for {SynergyId}: {Time}s",
            trialId, submission.SynergyId, submission.TimeSeconds);

        var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == submission.SynergyId);
        if (user == null)
        {
            return NotFound(new { error = "User not found" });
        }

        var trial = await _context.TimeTrials.FindAsync(trialId);
        if (trial == null || !trial.Active)
        {
            return NotFound(new { error = "Time trial not found or inactive" });
        }

        // Check if beat target time
        bool beatTarget = submission.TimeSeconds <= trial.TargetTime;
        int goldEarned = beatTarget ? trial.GoldReward : 0;
        int cashEarned = beatTarget ? trial.CashReward : trial.CashReward / 2; // Half cash for participation

        // Save result
        var result = new TimeTrialResult
        {
            UserId = user.Id,
            TimeTrialId = trialId,
            TimeSeconds = submission.TimeSeconds,
            SubmittedAt = DateTime.UtcNow,
            BeatTarget = beatTarget,
            GoldEarned = goldEarned,
            CashEarned = cashEarned
        };

        _context.TimeTrialResults.Add(result);

        // Award currency
        if (user.Gold == null) user.Gold = 0;
        if (user.Cash == null) user.Cash = 0;
        user.Gold += goldEarned;
        user.Cash += cashEarned;

        await _context.SaveChangesAsync();

        return Ok(new
        {
            success = true,
            beatTarget = beatTarget,
            timeSeconds = submission.TimeSeconds,
            targetTime = trial.TargetTime,
            goldEarned = goldEarned,
            cashEarned = cashEarned,
            totalGold = user.Gold,
            totalCash = user.Cash,
            message = beatTarget ? "🏆 Target time beaten!" : "Good try! Keep racing!"
        });
    }

    private async Task<int> CalculateStreak(int userId)
    {
        var rewards = await _context.DailyRewards
            .Where(r => r.UserId == userId && r.Claimed)
            .OrderByDescending(r => r.RewardDate)
            .ToListAsync();

        int streak = 0;
        var currentDate = DateTime.UtcNow.Date;

        foreach (var reward in rewards)
        {
            if (reward.RewardDate.Date == currentDate.AddDays(-streak))
            {
                streak++;
            }
            else
            {
                break;
            }
        }

        return streak;
    }
}

public class GoldPurchaseRequest
{
    public string SynergyId { get; set; } = string.Empty;
    public int GoldAmount { get; set; }
    public string? Sku { get; set; }
}

public class TimeTrialSubmission
{
    public string SynergyId { get; set; } = string.Empty;
    public double TimeSeconds { get; set; }
}
