using Indotalent.ConfigBackEnd.Exceptions;
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Indotalent.Features.Setting.Company.Cqrs;

public class UpdateCompanyRequest : CreateCompanyRequest
{
    public string? Id { get; set; }
    public DateTimeOffset? CreatedAt { get; set; }
    public string? CreatedBy { get; set; }
    public DateTimeOffset? UpdatedAt { get; set; }
    public string? UpdatedBy { get; set; }
}

public class UpdateCompanyResponse
{
    public string? Id { get; set; }
    public bool Success { get; set; }
}

public record UpdateCompanyCommand(UpdateCompanyRequest Data) : IRequest<UpdateCompanyResponse>;

public class UpdateCompanyHandler : IRequestHandler<UpdateCompanyCommand, UpdateCompanyResponse>
{
    private readonly AppDbContext _context;

    public UpdateCompanyHandler(AppDbContext context) => _context = context;

    public async Task<UpdateCompanyResponse> Handle(UpdateCompanyCommand request, CancellationToken cancellationToken)
    {
        var entity = await _context.Company
            .FirstOrDefaultAsync(x => x.Id == request.Data.Id, cancellationToken);

        if (entity == null) return new UpdateCompanyResponse { Id = request.Data.Id, Success = false };

        var isNameExists = await _context.Company
            .AnyAsync(x => x.Name == request.Data.Name && x.Id != request.Data.Id, cancellationToken);

        if (isNameExists)
        {
            throw new AlreadyExistsException("Company", request.Data.Name ?? string.Empty);
        }

        if (entity.IsDefault && !request.Data.IsDefault)
        {
            var totalCount = await _context.Company.CountAsync(cancellationToken);

            if (totalCount <= 1)
            {
                request.Data.IsDefault = true;
                throw new Exception("At least one company must be set as default.");
            }
        }

        if (request.Data.IsDefault)
        {
            var otherDefaults = await _context.Company
                .Where(x => x.IsDefault && x.Id != entity.Id)
                .ToListAsync(cancellationToken);

            foreach (var comp in otherDefaults)
            {
                comp.IsDefault = false;
            }
        }
        else
        {
            var anyOtherDefault = await _context.Company
                .AnyAsync(x => x.IsDefault && x.Id != entity.Id, cancellationToken);

            if (!anyOtherDefault)
            {
                request.Data.IsDefault = true;
            }
        }

        entity.Name = request.Data.Name ?? string.Empty;
        entity.Description = request.Data.Description ?? string.Empty;
        entity.IsDefault = request.Data.IsDefault;
        entity.CurrencyId = request.Data.CurrencyId ?? string.Empty;
        entity.TaxIdentification = request.Data.TaxIdentification ?? string.Empty;
        entity.BusinessLicense = request.Data.BusinessLicense ?? string.Empty;
        entity.StreetAddress = request.Data.StreetAddress ?? string.Empty;
        entity.City = request.Data.City ?? string.Empty;
        entity.StateProvince = request.Data.StateProvince ?? string.Empty;
        entity.ZipCode = request.Data.ZipCode ?? string.Empty;
        entity.Phone = request.Data.Phone ?? string.Empty;
        entity.Email = request.Data.Email ?? string.Empty;
        entity.SocialMediaLinkedIn = request.Data.SocialMediaLinkedIn ?? string.Empty;
        entity.SocialMediaX = request.Data.SocialMediaX ?? string.Empty;
        entity.SocialMediaFacebook = request.Data.SocialMediaFacebook ?? string.Empty;
        entity.SocialMediaInstagram = request.Data.SocialMediaInstagram ?? string.Empty;
        entity.SocialMediaTikTok = request.Data.SocialMediaTikTok ?? string.Empty;
        entity.OtherInformation1 = request.Data.OtherInformation1 ?? string.Empty;
        entity.OtherInformation2 = request.Data.OtherInformation2 ?? string.Empty;
        entity.OtherInformation3 = request.Data.OtherInformation3 ?? string.Empty;

        await _context.SaveChangesAsync(cancellationToken);

        return new UpdateCompanyResponse { Id = entity.Id, Success = true };
    }
}