using DoliMiddlewareApi.Dtos.command;
using DoliMiddlewareApi.Dtos.Dolibarr;
using DoliMiddlewareApi.Dtos.query;
using DoliMiddlewareApi.Exceptions;
using DoliMiddlewareApi.Mappers;
using DoliMiddlewareApi.Services.Clients;

namespace DoliMiddlewareApi.Services;

public class ClientService(IDolibarrApiClient apiClient)
{
    public async Task<List<ClientDto>> GetClientsAsync(int limit = 50, int page = 1, bool supplier = false)
    {
        var endpoint = $"thirdparties?limit={limit}&page={page - 1}";
        if (supplier) endpoint += "&mode=4";

        var clients = await apiClient.GetCollectionAsync<ClientResponse>(endpoint);

        if (clients.Count == 0)
            return clients.Select(ClientMapper.MapToClientDtoWithoutContacts).ToList();

        var clientIds = string.Join(",", clients.Select(c => c.id).Where(id => !string.IsNullOrEmpty(id)));

        var contacts = await apiClient.GetCollectionAsync<ContactResponse>($"contacts?thirdparty_ids={clientIds}");
        var contactDtos = contacts.Select(ContactMapper.MapToContactDto).ToList();

        return clients.Select(c => ClientMapper.MapToClientDto(c, contactDtos)).ToList();
    }

    public async Task<ClientDetailDto> GetClientAsync(int id)
    {
        var client = await apiClient.GetResourceAsync<ClientResponse>($"thirdparties/{id}");

        List<ContactDto> contactDtos = new();
        try
        {
            var contacts = await apiClient.GetCollectionAsync<ContactResponse>($"contacts?thirdparty_ids={id}");
            contactDtos = contacts.Select(ContactMapper.MapToContactDto).ToList();
        }
        catch (ApiException)
        {
            // Contacts may fail or be empty, continue without them
        }

        return ClientMapper.MapToClientDetailDto(client, contactDtos);
    }

    public async Task<int> CreateClientAsync(CreateClientDto dto)
    {
        var isSupplier = dto.Role == "supplier" || dto.Role == "both";
        var isClient   = dto.Role != "supplier";

        var requestBody = new Dictionary<string, object?>
        {
            ["name"] = dto.Name,
            ["client"] = isClient ? "1" : "0",
            ["fournisseur"] = isSupplier ? "1" : "0",
            ["address"] = dto.Address,
            ["zip"] = dto.Zip,
            ["town"] = dto.Town,
            ["phone"] = dto.Phone,
            ["email"] = dto.Email,
            ["country_code"] = dto.CountryCode,
            ["tva_intra"] = dto.VatNumber,
            ["url"] = dto.Url,
            ["note_public"] = dto.NotePublic,
            ["note_private"] = dto.NotePrivate
        };

        var response = await apiClient.PostAsync("thirdparties", requestBody);
        return int.Parse(response);
    }

    public async Task UpdateClientAsync(int id, UpdateClientDto dto)
    {
        var current = await apiClient.GetResourceAsync<ClientResponse>($"thirdparties/{id}");

        var requestBody = new Dictionary<string, object?>
        {
            ["name"] = dto.Name ?? current.name,
            ["address"] = dto.Address ?? current.address,
            ["zip"] = dto.Zip ?? current.zip,
            ["town"] = dto.Town ?? current.town,
            ["phone"] = dto.Phone ?? current.phone,
            ["email"] = dto.Email ?? current.email,
            ["country_code"] = dto.CountryCode ?? current.country_code,
            ["tva_intra"] = dto.VatNumber ?? current.tva_intra,
            ["url"] = dto.Url ?? current.url,
            ["note_public"] = dto.NotePublic ?? current.note_public,
            ["note_private"] = dto.NotePrivate ?? current.note_private
        };

        await apiClient.PutAsync($"thirdparties/{id}", requestBody);
    }

    public async Task DeleteClientAsync(int id)
    {
        await apiClient.DeleteAsync($"thirdparties/{id}");
    }
}