using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.Internal;
using CashLineERP.Contracts.Notifications;

namespace CashLineERP.Api.Tests;

public sealed class NotificationTemplateAndOrchestrationQaTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

    public NotificationTemplateAndOrchestrationQaTests(ApiTestFactory factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Notification_Template_And_Queue_Endpoints_Work_End_To_End()
    {
        await _client.AuthenticateAsInternalAsync();

        var createResponse = await _client.PostAsJsonAsync("/api/v1/notifications/templates", new CreateNotificationTemplateRequest(
            TemplateName: "Payment reminder",
            ChannelCode: "EMAIL",
            SubjectTemplate: "Reminder {{invoiceNumber}}",
            BodyTemplate: "Dear {{partyName}}, invoice {{invoiceNumber}} is due.",
            Notes: "HTTP notification template"));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);

        var createdTemplate = await createResponse.Content.ReadFromJsonAsync<NotificationTemplateResponse>();
        Assert.NotNull(createdTemplate);

        var submitResponse = await _client.PostAsync($"/api/v1/notifications/templates/{createdTemplate!.NotificationTemplateId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitResponse.StatusCode);

        var approvalQueueResponse = await _client.GetAsync("/api/v1/internal/work-queues/approvals?moduleCode=OPERATIONS");
        Assert.Equal(HttpStatusCode.OK, approvalQueueResponse.StatusCode);
        var approvalQueue = await approvalQueueResponse.Content.ReadFromJsonAsync<InternalApprovalQueueItemResponse[]>();
        Assert.NotNull(approvalQueue);
        Assert.Contains(approvalQueue!, item => item.DocumentType == "NOTIFICATION_TEMPLATE" && item.DocumentId == createdTemplate.NotificationTemplateId);

        await _client.AuthenticateAsFinanceCheckerAsync();
        var approveResponse = await _client.PostAsync($"/api/v1/notifications/templates/{createdTemplate.NotificationTemplateId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveResponse.StatusCode);
        var activateResponse = await _client.PostAsync($"/api/v1/notifications/templates/{createdTemplate.NotificationTemplateId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);

        await _client.AuthenticateAsInternalAsync();
        var enqueueResponse = await _client.PostAsJsonAsync("/api/v1/notifications/orchestrations/enqueue", new EnqueueNotificationRequest(
            NotificationTemplateId: createdTemplate.NotificationTemplateId,
            RecipientReference: "ar@example.com",
            ContextCode: "COLLECTIONS",
            RelatedEntityType: "AR_INVOICE",
            RelatedEntityId: 1,
            Variables: new Dictionary<string, string?>
            {
                ["partyName"] = "CashLine Customer",
                ["invoiceNumber"] = "ARINV-000001"
            }));
        Assert.Equal(HttpStatusCode.OK, enqueueResponse.StatusCode);
        var queueItem = await enqueueResponse.Content.ReadFromJsonAsync<NotificationQueueItemResponse>();
        Assert.NotNull(queueItem);
        Assert.Equal("PENDING", queueItem!.StatusCode);

        var listResponse = await _client.GetAsync("/api/v1/notifications/queue?statusCode=PENDING&channelCode=EMAIL");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
        var queueItems = await listResponse.Content.ReadFromJsonAsync<NotificationQueueItemResponse[]>();
        Assert.NotNull(queueItems);
        Assert.Contains(queueItems!, item => item.NotificationQueueItemId == queueItem.NotificationQueueItemId);

        var deadLetterResponse = await _client.PostAsJsonAsync($"/api/v1/notifications/queue/{queueItem.NotificationQueueItemId}/dead-letter", new NotificationDeadLetterRequest(
            ReasonText: "SMTP unreachable"));
        Assert.Equal(HttpStatusCode.OK, deadLetterResponse.StatusCode);

        var replayResponse = await _client.PostAsJsonAsync($"/api/v1/notifications/queue/{queueItem.NotificationQueueItemId}/replay", new NotificationReplayRequest(
            ReplayReasonText: "Mail restored",
            DelaySeconds: 0));
        Assert.Equal(HttpStatusCode.OK, replayResponse.StatusCode);

        var sendResponse = await _client.PostAsJsonAsync("/api/v1/notifications/queue/send-batch", new NotificationSendBatchRequest(
            SenderCode: "HTTP_NOTIFICATION_WORKER",
            BatchSize: 10));
        Assert.Equal(HttpStatusCode.OK, sendResponse.StatusCode);
        var sendResult = await sendResponse.Content.ReadFromJsonAsync<NotificationSendBatchResultResponse>();
        Assert.NotNull(sendResult);
        Assert.Contains(sendResult!.SentItems, item => item.NotificationQueueItemId == queueItem.NotificationQueueItemId && item.StatusCode == "SENT");
    }
}
