using CashLineERP.Domain.Common;
using CashLineERP.SharedKernel.Workflow;

namespace CashLineERP.Domain.Notifications;

public sealed class NotificationTemplate : Entity
{
    public long Id { get; private set; }
    public string TemplateCode { get; private set; } = string.Empty;
    public string TemplateName { get; private set; } = string.Empty;
    public string ChannelCode { get; private set; } = string.Empty;
    public string? SubjectTemplate { get; private set; }
    public string BodyTemplate { get; private set; } = string.Empty;
    public long StatusId { get; private set; } = WorkflowStatusSeedIds.Draft;
    public bool IsActive { get; private set; }
    public string? Notes { get; private set; }
    public DateTime? SubmittedAtUtc { get; private set; }
    public long? SubmittedByUserId { get; private set; }
    public DateTime? ApprovedAtUtc { get; private set; }
    public long? ApprovedByUserId { get; private set; }
    public DateTime? ActivatedAtUtc { get; private set; }
    public long? ActivatedByUserId { get; private set; }

    public NotificationTemplate(
        string templateCode,
        string templateName,
        string channelCode,
        string? subjectTemplate,
        string bodyTemplate,
        string? notes)
    {
        if (string.IsNullOrWhiteSpace(templateCode))
        {
            throw new InvalidOperationException("Notification template code is required.");
        }

        if (string.IsNullOrWhiteSpace(templateName))
        {
            throw new InvalidOperationException("Notification template name is required.");
        }

        if (string.IsNullOrWhiteSpace(channelCode))
        {
            throw new InvalidOperationException("Notification template channel is required.");
        }

        if (string.IsNullOrWhiteSpace(bodyTemplate))
        {
            throw new InvalidOperationException("Notification template body is required.");
        }

        TemplateCode = templateCode.Trim().ToUpperInvariant();
        TemplateName = templateName.Trim();
        ChannelCode = channelCode.Trim().ToUpperInvariant();
        SubjectTemplate = string.IsNullOrWhiteSpace(subjectTemplate) ? null : subjectTemplate.Trim();
        BodyTemplate = bodyTemplate.Trim();
        Notes = string.IsNullOrWhiteSpace(notes) ? null : notes.Trim();
    }

    private NotificationTemplate()
    {
    }

    public void Submit(long actorUserId)
    {
        if (StatusId != WorkflowStatusSeedIds.Draft && StatusId != WorkflowStatusSeedIds.Returned)
        {
            throw new InvalidOperationException("Only draft or returned notification templates can be submitted.");
        }

        StatusId = WorkflowStatusSeedIds.Submitted;
        SubmittedAtUtc = DateTime.UtcNow;
        SubmittedByUserId = actorUserId;
        ApprovedAtUtc = null;
        ApprovedByUserId = null;
        Touch(actorUserId);
    }

    public void Approve(long actorUserId)
    {
        if (StatusId == WorkflowStatusSeedIds.Approved)
        {
            return;
        }

        if (StatusId != WorkflowStatusSeedIds.Submitted)
        {
            throw new InvalidOperationException("Only submitted notification templates can be approved.");
        }

        if (SubmittedByUserId == actorUserId)
        {
            throw new InvalidOperationException("Notification template maker-checker control prohibits self-approval.");
        }

        StatusId = WorkflowStatusSeedIds.Approved;
        ApprovedAtUtc = DateTime.UtcNow;
        ApprovedByUserId = actorUserId;
        Touch(actorUserId);
    }

    public void Activate(long actorUserId)
    {
        if (StatusId != WorkflowStatusSeedIds.Approved)
        {
            throw new InvalidOperationException("Only approved notification templates can be activated.");
        }

        IsActive = true;
        ActivatedAtUtc = DateTime.UtcNow;
        ActivatedByUserId = actorUserId;
        Touch(actorUserId);
    }
}
