namespace Service;

public interface IBudgetService
{
    Task<List<BudgetRecord>> GetAllAsync();
    Task<BudgetRecord?> GetByIdAsync(long id);
    Task<bool> AddAsync(BudgetRecord budget);
    Task<bool> DeleteAsync(long id);
    Task<bool> UpdateAsync(BudgetRecord budget);
    Task<decimal> CalculateCurrentAmountAsync(BudgetRecord budget, DateTime? now = null);
    Task<bool> ToggleStopAsync(long id);
}

public class BudgetService(
    IBudgetRepository budgetRepository
) : IBudgetService
{
    public async Task<List<BudgetRecord>> GetAllAsync()
    {
        var list = await budgetRepository.GetAllAsync();
        return list.ToList();
    }

    public async Task<BudgetRecord?> GetByIdAsync(long id)
    {
        return await budgetRepository.GetByIdAsync(id);
    }

    public async Task<bool> AddAsync(BudgetRecord budget)
    {
        return await budgetRepository.AddAsync(budget);
    }

    public async Task<bool> DeleteAsync(long id)
    {
        return await budgetRepository.DeleteAsync(id);
    }

    public async Task<bool> UpdateAsync(BudgetRecord budget)
    {
        return await budgetRepository.UpdateAsync(budget);
    }

    public async Task<bool> ToggleStopAsync(long id)
    {
        var budget = await budgetRepository.GetByIdAsync(id);
        if (budget == null) return false;
        budget.IsStopped = !budget.IsStopped;
        return await budgetRepository.UpdateAsync(budget);
    }

    public async Task<decimal> CalculateCurrentAmountAsync(BudgetRecord budget, DateTime? now = null)
    {
        if (budget.IsStopped) return 0;

        var referenceDate = now ?? DateTime.Now;
        var (startDate, endDate) = GetPeriodRange(budget.StartDate, budget.Type, referenceDate);

        return await budgetRepository.GetCurrentAmountAsync(budget, startDate, endDate);
    }

    public static (DateTime start, DateTime end) GetPeriodRange(DateTime startDate, BudgetPeriodType type, DateTime referenceDate)
    {
        DateTime start;
        DateTime end;

        if (type == BudgetPeriodType.Month)
        {
            start = new DateTime(referenceDate.Year, referenceDate.Month, 1);
            end = start.AddMonths(1).AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
        }
        else if (type == BudgetPeriodType.Year)
        {
            start = new DateTime(referenceDate.Year, 1, 1);
            end = new DateTime(referenceDate.Year, 12, 31).AddHours(23).AddMinutes(59).AddSeconds(59);
        }
        else
        {
            start = startDate;
            end = DateTime.MaxValue;
        }

        return (start, end);
    }
}
