using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;

namespace OTSSignsOrchestrator.Server.Services;

public class EmailOptions
{
    public const string Section = "Email";
    public string SendGridApiKey { get; set; } = string.Empty;
    public string SenderEmail { get; set; } = "noreply@otssigns.com";
    public string SenderName { get; set; } = "OTS Signs";
}

/// <summary>
/// Email service backed by SendGrid. All methods catch exceptions, log as Error,
/// and return bool success — they never throw.
/// </summary>
public class EmailService
{
    private readonly ILogger<EmailService> _logger;
    private readonly EmailOptions _options;
    private readonly SendGridClient? _client;

    public EmailService(ILogger<EmailService> logger, IOptions<EmailOptions> options)
    {
        _logger = logger;
        _options = options.Value;

        if (!string.IsNullOrWhiteSpace(_options.SendGridApiKey))
        {
            _client = new SendGridClient(_options.SendGridApiKey);
        }
        else
        {
            _logger.LogWarning("SendGrid API key not configured — emails will be logged only");
        }
    }

    public async Task<bool> SendWelcomeEmailAsync(
        string toEmail, string firstName, string instanceUrl, string invitationLink)
    {
        var subject = "Welcome to OTS Signs — Your CMS is Ready!";
        var html = $"""
            <h2>Welcome to OTS Signs, {HtmlEncode(firstName)}!</h2>
            <p>Your Xibo CMS instance has been provisioned and is ready to use.</p>
            <p><strong>Instance URL:</strong> <a href="{HtmlEncode(instanceUrl)}">{HtmlEncode(instanceUrl)}</a></p>
            <p><strong>Accept your invitation to get started:</strong></p>
            <p><a href="{HtmlEncode(invitationLink)}" style="display:inline-block;padding:12px 24px;background-color:#3B82F6;color:#fff;text-decoration:none;border-radius:6px;">Accept Invitation</a></p>
            <p>If you have any questions, please contact our support team.</p>
            <p>— The OTS Signs Team</p>
            """;

        return await SendEmailAsync(toEmail, subject, html);
    }

    public async Task<bool> SendPaymentFailedEmailAsync(
        string toEmail, string companyName, int failedCount)
    {
        var daysSinceFirst = failedCount * 3; // approximate
        string subject;
        string urgency;

        if (daysSinceFirst >= 21)
        {
            subject = $"FINAL NOTICE — Payment Required for {companyName}";
            urgency = "<p style=\"color:#DC2626;font-weight:bold;\">⚠️ FINAL NOTICE: Your service will be suspended if payment is not received immediately.</p>";
        }
        else if (daysSinceFirst >= 7)
        {
            subject = $"URGENT — Payment Failed for {companyName}";
            urgency = "<p style=\"color:#F59E0B;font-weight:bold;\">⚠️ URGENT: Please update your payment method to avoid service interruption.</p>";
        }
        else
        {
            subject = $"Payment Failed for {companyName}";
            urgency = "<p>Please update your payment method at your earliest convenience.</p>";
        }

        var html = $"""
            <h2>Payment Failed — {HtmlEncode(companyName)}</h2>
            {urgency}
            <p>We were unable to process your payment (attempt #{failedCount}).</p>
            <p>Please update your payment method to keep your OTS Signs service active.</p>
            <p>— The OTS Signs Team</p>
            """;

        return await SendEmailAsync(toEmail, subject, html);
    }

    public async Task<bool> SendTrialEndingEmailAsync(
        string toEmail, string firstName, DateTime trialEndDate)
    {
        var daysLeft = (int)Math.Ceiling((trialEndDate - DateTime.UtcNow).TotalDays);
        var subject = $"Your OTS Signs Trial Ends in {Math.Max(0, daysLeft)} Day{(daysLeft != 1 ? "s" : "")}";
        var html = $"""
            <h2>Hi {HtmlEncode(firstName)},</h2>
            <p>Your OTS Signs trial ends on <strong>{trialEndDate:MMMM dd, yyyy}</strong>.</p>
            <p>To continue using your CMS without interruption, please subscribe before your trial expires.</p>
            <p>— The OTS Signs Team</p>
            """;

        return await SendEmailAsync(toEmail, subject, html);
    }

    public async Task<bool> SendReportEmailAsync(
        string toEmail, string attachmentName, byte[] attachment, string mimeType)
    {
        var subject = $"OTS Signs Report — {attachmentName}";
        var html = $"""
            <h2>OTS Signs Report</h2>
            <p>Please find the attached report: <strong>{HtmlEncode(attachmentName)}</strong></p>
            <p>This report was generated automatically by the OTS Signs Orchestrator.</p>
            <p>— The OTS Signs Team</p>
            """;

        return await SendEmailAsync(toEmail, subject, html, attachmentName, attachment, mimeType);
    }

    private async Task<bool> SendEmailAsync(
        string toEmail,
        string subject,
        string htmlContent,
        string? attachmentName = null,
        byte[]? attachmentData = null,
        string? attachmentMimeType = null)
    {
        try
        {
            if (_client is null)
            {
                _logger.LogWarning(
                    "SendGrid not configured — would send email to {Email}: {Subject}",
                    toEmail, subject);
                return true; // Not a failure — just not configured
            }

            var from = new EmailAddress(_options.SenderEmail, _options.SenderName);
            var to = new EmailAddress(toEmail);
            var msg = MailHelper.CreateSingleEmail(from, to, subject, null, htmlContent);

            if (attachmentData is not null && attachmentName is not null)
            {
                msg.AddAttachment(
                    attachmentName,
                    Convert.ToBase64String(attachmentData),
                    attachmentMimeType ?? "application/octet-stream");
            }

            var response = await _client.SendEmailAsync(msg);

            if (response.IsSuccessStatusCode)
            {
                _logger.LogInformation("Email sent to {Email}: {Subject}", toEmail, subject);
                return true;
            }

            var body = await response.Body.ReadAsStringAsync();
            _logger.LogError(
                "SendGrid returned {StatusCode} for email to {Email}: {Body}",
                response.StatusCode, toEmail, body);
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to send email to {Email}: {Subject}", toEmail, subject);
            return false;
        }
    }

    private static string HtmlEncode(string value) =>
        System.Net.WebUtility.HtmlEncode(value);
}
