using CMSMicroservice.Protobuf.Protos;
using Google.Protobuf.WellKnownTypes;

namespace BackOffice.Services.PublicMessage;

public class PublicMessageService : IPublicMessageService
{
    private readonly PublicMessageContract.PublicMessageContractClient _client;

    public PublicMessageService(PublicMessageContract.PublicMessageContractClient client)
    {
        _client = client;
    }

    public async Task<(List<PublicMessageDto> Messages, int TotalCount)> GetMessagesAsync(MessageFilterDto? filter = null)
    {
        filter ??= new MessageFilterDto();

        var request = new GetAllMessagesRequest
        {
            PageNumber = filter.PageNumber,
            PageSize = filter.PageSize
        };

        // CMS proto uses IsActive (BoolValue) instead of Status (int)
        if (filter.Status.HasValue)
        {
            // Map: Draft=0 → inactive, Published=1 → active, Archived=2 → inactive
            request.IsActive = filter.Status.Value == MessageStatus.Published;
        }

        // CMS proto uses Type (Int32Value) instead of MessageType (int)
        if (filter.Type.HasValue)
        {
            request.Type = (int)filter.Type.Value;
        }

        var response = await _client.GetAllMessagesAsync(request);

        var messages = response.Messages.Select(m => new PublicMessageDto
        {
            Id = m.Id,
            Title = m.Title,
            Type = (MessageType)m.Type,
            TypeName = m.TypeName,
            Priority = m.Priority,
            PriorityName = m.PriorityName,
            // CMS uses IsActive (bool) instead of Status enum
            Status = m.IsActive ? MessageStatus.Published : MessageStatus.Draft,
            StatusName = m.IsActive ? "فعال" : "غیرفعال",
            StartsAt = m.StartsAt?.ToDateTime(),
            ExpiresAt = m.ExpiresAt?.ToDateTime(),
            Created = m.Created?.ToDateTime()
        }).ToList();

        return (messages, (int)(response.MetaData?.TotalCount ?? 0));
    }

    public async Task<PublicMessageDetailsDto?> GetByIdAsync(long id)
    {
        var request = new GetPublicMessageRequest { MessageId = id };
        var response = await _client.GetPublicMessageAsync(request);

        if (response.Id == 0)
            return null;

        return new PublicMessageDetailsDto
        {
            Id = response.Id,
            Title = response.Title,
            Content = response.Content,
            Type = (MessageType)response.Type,
            TypeName = string.Empty, // CMS GetPublicMessageResponse does not include TypeName
            Priority = response.Priority,
            PriorityName = string.Empty, // CMS GetPublicMessageResponse does not include PriorityName
            // CMS uses IsActive/IsArchived bools instead of Status enum
            Status = response.IsArchived ? MessageStatus.Archived : (response.IsActive ? MessageStatus.Published : MessageStatus.Draft),
            StatusName = response.IsArchived ? "آرشیو شده" : (response.IsActive ? "فعال" : "غیرفعال"),
            StartsAt = response.StartDate?.ToDateTime(),
            ExpiresAt = response.EndDate?.ToDateTime(),
            PublishedAt = response.PublishedAt?.ToDateTime(),
            ArchivedAt = response.ArchivedAt?.ToDateTime(),
            IsDismissible = false, // CMS does not have IsDismissible
            TargetAudience = null, // CMS does not have TargetAudience
            Tags = new List<string>(), // CMS does not have Tags
            Created = response.CreatedAt?.ToDateTime(),
            LastModified = response.LastModifiedAt?.ToDateTime()
        };
    }

    public async Task<long> CreateAsync(CreatePublicMessageDto dto)
    {
        var request = new CreatePublicMessageRequest
        {
            Title = dto.Title,
            Content = dto.Content,
            Type = (int)dto.Type, // CMS uses Type instead of MessageType
            Priority = dto.Priority
            // CMS does not have IsDismissible or TargetAudience fields
        };

        if (dto.StartsAt.HasValue)
        {
            request.StartDate = Timestamp.FromDateTime(dto.StartsAt.Value.ToUniversalTime());
        }

        if (dto.ExpiresAt.HasValue)
        {
            request.EndDate = Timestamp.FromDateTime(dto.ExpiresAt.Value.ToUniversalTime());
        }

        // CMS does not have Tags field in CreatePublicMessageRequest

        var response = await _client.CreatePublicMessageAsync(request);
        return response.Id;
    }

    public async Task UpdateAsync(long id, UpdatePublicMessageDto dto)
    {
        var request = new UpdatePublicMessageRequest
        {
            Id = id, // CMS uses Id instead of MessageId
            Title = dto.Title,
            Content = dto.Content,
            Type = (int)dto.Type, // CMS uses Type instead of MessageType
            Priority = dto.Priority
            // CMS does not have IsDismissible or TargetAudience fields
        };

        if (dto.StartsAt.HasValue)
        {
            request.StartDate = Timestamp.FromDateTime(dto.StartsAt.Value.ToUniversalTime());
        }

        if (dto.ExpiresAt.HasValue)
        {
            request.EndDate = Timestamp.FromDateTime(dto.ExpiresAt.Value.ToUniversalTime());
        }

        // CMS does not have Tags field in UpdatePublicMessageRequest

        await _client.UpdatePublicMessageAsync(request);
    }

    public async Task DeleteAsync(long id)
    {
        var request = new DeletePublicMessageRequest { MessageId = id };
        await _client.DeletePublicMessageAsync(request);
    }

    public async Task PublishAsync(long id)
    {
        var request = new PublishMessageRequest { MessageId = id };
        await _client.PublishMessageAsync(request);
    }

    public async Task ArchiveAsync(long id)
    {
        var request = new ArchiveMessageRequest { MessageId = id };
        await _client.ArchiveMessageAsync(request);
    }
}
