using JSMR.Application.Tags.Commands.SetEnglishName;
using JSMR.Application.Tags.Commands.UpdateTagStatus;
using JSMR.Application.Tags.Contracts;
using JSMR.Application.Tags.Ports;
using JSMR.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace JSMR.Infrastructure.Data.Repositories.Tags;

public class TagWriter(AppDbContext context) : ITagWriter
{
    public async Task<SetTagEnglishNameResponse> SetEnglishNameAsync(SetTagEnglishNameRequest request, CancellationToken cancellationToken = default)
    {
        Tag tag = await GetTagAsync(request.TagId, cancellationToken);
        EnglishTag? englishTag = await context.EnglishTags.FirstOrDefaultAsync(e => e.TagId == request.TagId, cancellationToken);

        if (englishTag is null)
        {
            englishTag = new EnglishTag
            {
                TagId = request.TagId,
                Name = request.EnglishName
            };

            context.EnglishTags.Add(englishTag);
        }
        else
        {
            englishTag.Name = request.EnglishName;
        }

        await context.SaveChangesAsync(cancellationToken);

        return new SetTagEnglishNameResponse(request.TagId, request.EnglishName);
    }

    public async Task<UpdateTagStatusResponse> UpdateStatusAsync(UpdateTagStatusRequest request, CancellationToken cancellationToken = default)
    {
        Tag tag = await GetTagAsync(request.TagId, cancellationToken);

        switch (request.TagStatus)
        {
            case TagStatus.Neutral:
                tag.Favorite = false;
                tag.Blacklisted = false;
                break;
            case TagStatus.Favorite:
                tag.Favorite = true;
                tag.Blacklisted = false;
                break;
            case TagStatus.Blacklisted:
                tag.Favorite = false;
                tag.Blacklisted = true;
                break;
        }

        await context.SaveChangesAsync(cancellationToken);

        return new UpdateTagStatusResponse(request.TagId, request.TagStatus);
    }

    private async Task<Tag> GetTagAsync(int tagId, CancellationToken cancellationToken)
    {
        return await context.Tags.FirstOrDefaultAsync(tag => tag.TagId == tagId, cancellationToken)
            ?? throw new KeyNotFoundException($"Tag {tagId} not found.");
    }
}