using System.Net.Http.Headers;
using System.Net.Http.Json;

namespace ROLAC.API.Services.Notifications;

/// <summary>Sends text messages and replies via the Line Messaging API REST endpoints.</summary>
public sealed class LineMessageChannel : IMessageChannel
{
    private const string PushUrl  = "https://api.line.me/v2/bot/message/push";
    private const string ReplyUrl = "https://api.line.me/v2/bot/message/reply";

    private readonly HttpClient _http;
    private readonly INotificationSettingsService _settings;

    public LineMessageChannel(HttpClient http, INotificationSettingsService settings)
    {
        _http = http;
        _settings = settings;
    }

    public Task<MessageSendResult> PushToUserAsync(string externalId, string text, CancellationToken ct = default)
        => PostAsync(PushUrl, new { to = externalId, messages = new[] { new { type = "text", text } } }, ct);

    public Task<MessageSendResult> PushToGroupAsync(string externalId, string text, CancellationToken ct = default)
        => PostAsync(PushUrl, new { to = externalId, messages = new[] { new { type = "text", text } } }, ct);

    public Task<MessageSendResult> ReplyAsync(string replyToken, string text, CancellationToken ct = default)
        => PostAsync(ReplyUrl, new { replyToken, messages = new[] { new { type = "text", text } } }, ct);

    private async Task<MessageSendResult> PostAsync(string url, object payload, CancellationToken ct)
    {
        try
        {
            using var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = JsonContent.Create(payload),
            };
            request.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", _settings.GetLine().ChannelAccessToken);

            using var response = await _http.SendAsync(request, ct);
            if (response.IsSuccessStatusCode) return new MessageSendResult(true, null);

            var body = await response.Content.ReadAsStringAsync(ct);
            return new MessageSendResult(false, $"{(int)response.StatusCode}: {body}");
        }
        catch (Exception ex)
        {
            return new MessageSendResult(false, ex.Message);
        }
    }
}
