using JSMR.Application.Circles.Commands.UpdateCircleStatus;
using JSMR.Application.Circles.Contracts;
using JSMR.Application.Circles.Ports;
using JSMR.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace JSMR.Infrastructure.Data.Repositories.Circles;

public class CircleWriter(AppDbContext context) : ICircleWriter
{
    public async Task<UpdateCircleStatusResponse> UpdateStatusAsync(UpdateCircleStatusRequest request, CancellationToken cancellationToken = default)
    {
        Circle circle = await GetCircleAsync(request.CircleId, cancellationToken);
        CircleStatus oldStatus = GetCircleStatus(circle);

        switch (request.CircleStatus)
        {
            case CircleStatus.Neutral:
                circle.Favorite = false;
                circle.Blacklisted = false;
                circle.Spam = false;
                break;
            case CircleStatus.Favorite:
                circle.Favorite = true;
                circle.Blacklisted = false;
                circle.Spam = false;
                break;
            case CircleStatus.Blacklisted:
                circle.Favorite = false;
                circle.Blacklisted = true;
                circle.Spam = false;
                break;
            case CircleStatus.Spam:
                circle.Favorite = false;
                circle.Blacklisted = false;
                circle.Spam = true;
                break;
        }

        await context.SaveChangesAsync(cancellationToken);

        CircleStatus newStatus = GetCircleStatus(circle);

        return new UpdateCircleStatusResponse(request.CircleId, oldStatus, newStatus);
    }

    private static CircleStatus GetCircleStatus(Circle circle)
    {
        if (circle.Favorite)
            return CircleStatus.Favorite;

        if (circle.Blacklisted)
            return CircleStatus.Blacklisted;

        if (circle.Spam)
            return CircleStatus.Spam;

        return CircleStatus.Neutral;
    }

    private async Task<Circle> GetCircleAsync(int circleId, CancellationToken cancellationToken)
    {
        return await context.Circles.FirstOrDefaultAsync(circle => circle.CircleId == circleId, cancellationToken)
            ?? throw new KeyNotFoundException($"Circle {circleId} not found.");
    }
}