import { SendEmailCommand, SendRawEmailCommand } from '@aws-sdk/client-ses';
import { sesClient } from '@/lib/sesClient';
import config from '@/shared/config/config';
import { EmailRecipient, EmailAttachment } from './email.interfaces';
import { estimateEmailSize } from '@/shared/utils/commonHelper';

// SES 10MB limit in bytes
const SES_MAX_SIZE_BYTES = 10 * 1024 * 1024;
import { buildRawSesMimeMessage } from './sesMimeBuilder';

export interface SESEmailOptions {
    to: string | string[] | EmailRecipient[];
    cc?: string | string[] | EmailRecipient[];
    subject: string;
    htmlContent?: string;
    textContent?: string;
    attachments?: EmailAttachment[];
}

/**
 * Format email addresses for SES
 */
const formatEmailAddresses = (
    addresses: string | string[] | EmailRecipient[],
): string[] => {
    if (typeof addresses === 'string') {
        return [addresses];
    }

    if (Array.isArray(addresses)) {
        return addresses.map((addr) => {
            if (typeof addr === 'string') {
                return addr;
            }
            // Handle EmailRecipient format
            return addr.email;
        });
    }

    return [];
};


/**
 * Build MIME message with attachments
 */
const buildMimeMessage = (
    from: string,
    to: string[],
    cc: string[] | undefined,
    subject: string,
    textContent?: string,
    htmlContent?: string,
    attachments?: EmailAttachment[],
): string => {
    const boundary = `----=_NextPart_${Date.now()}_${Math.random().toString(36)}`;
    const attachmentBoundary = `----=_Attachment_${Date.now()}_${Math.random().toString(36)}`;
    
    let mimeMessage = '';
    
    // Headers
    mimeMessage += `From: ${from}\r\n`;
    mimeMessage += `To: ${to.join(', ')}\r\n`;
    if (cc && cc.length > 0) {
        mimeMessage += `Cc: ${cc.join(', ')}\r\n`;
    }
    mimeMessage += `Subject: ${subject}\r\n`;
    mimeMessage += `MIME-Version: 1.0\r\n`;
    mimeMessage += `Content-Type: multipart/mixed; boundary="${boundary}"\r\n\r\n`;
    
    // Message body
    mimeMessage += `--${boundary}\r\n`;
    
    if (textContent && htmlContent) {
        // Mixed content
        const contentBoundary = `----=_Content_${Date.now()}_${Math.random().toString(36)}`;
        mimeMessage += `Content-Type: multipart/alternative; boundary="${contentBoundary}"\r\n\r\n`;
        
        // Text part
        mimeMessage += `--${contentBoundary}\r\n`;
        mimeMessage += `Content-Type: text/plain; charset=UTF-8\r\n`;
        mimeMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
        mimeMessage += `${textContent}\r\n\r\n`;
        
        // HTML part
        mimeMessage += `--${contentBoundary}\r\n`;
        mimeMessage += `Content-Type: text/html; charset=UTF-8\r\n`;
        mimeMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
        mimeMessage += `${htmlContent}\r\n\r\n`;
        
        mimeMessage += `--${contentBoundary}--\r\n`;
    } else if (htmlContent) {
        // HTML only
        mimeMessage += `Content-Type: text/html; charset=UTF-8\r\n`;
        mimeMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
        mimeMessage += `${htmlContent}\r\n\r\n`;
    } else if (textContent) {
        // Text only
        mimeMessage += `Content-Type: text/plain; charset=UTF-8\r\n`;
        mimeMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
        mimeMessage += `${textContent}\r\n\r\n`;
    }
    
    // Attachments
    if (attachments && attachments.length > 0) {
        for (const attachment of attachments) {
            if (attachment.content) {
                const buffer = Buffer.isBuffer(attachment.content) 
                    ? attachment.content 
                    : Buffer.from(attachment.content, 'utf8');
                const base64Content = buffer.toString('base64');
                const contentType = attachment.contentType || 'application/octet-stream';
                const filename = attachment.name || 'attachment';
                
                mimeMessage += `--${boundary}\r\n`;
                mimeMessage += `Content-Type: ${contentType}; name="${filename}"\r\n`;
                mimeMessage += `Content-Transfer-Encoding: base64\r\n`;
                mimeMessage += `Content-Disposition: attachment; filename="${filename}"\r\n\r\n`;
                
                // Split base64 content into 76-character lines
                for (let i = 0; i < base64Content.length; i += 76) {
                    mimeMessage += base64Content.substring(i, i + 76) + '\r\n';
                }
                mimeMessage += '\r\n';
            }
        }
    }
    
    mimeMessage += `--${boundary}--\r\n`;
    
    return mimeMessage;
};

/**
 * Send email using AWS SES
 * @param options - Email options
 * @returns Promise with message ID or false on error
 */
export const sendSESEmail = async (
    options: SESEmailOptions,
): Promise<{ messageId: string } | false> => {
    try {
        const {
            to,
            cc,
            subject,
            htmlContent,
            textContent,
            attachments,
        } = options;

        const toAddresses = formatEmailAddresses(to);
        const ccAddresses = cc ? formatEmailAddresses(cc) : undefined;

        // Validate email size before sending
        const estimatedSize = estimateEmailSize(
            textContent,
            htmlContent,
            attachments,
        );

        if (estimatedSize > SES_MAX_SIZE_BYTES) {
            console.error(
                `Email exceeds SES 10MB limit. Size: ${(estimatedSize / 1024 / 1024).toFixed(2)} MB`,
            );
            throw new Error(
                `Email size exceeds SES 10MB limit (${(estimatedSize / 1024 / 1024).toFixed(2)} MB)`,
            );
        }

        // If no attachments, use simple SendEmailCommand
        if (!attachments || attachments.length === 0) {
            const command = new SendEmailCommand({
                Source: config.ses.senderEmail,
                Destination: {
                    ToAddresses: toAddresses,
                    ...(ccAddresses && ccAddresses.length > 0 && {
                        CcAddresses: ccAddresses,
                    }),
                },
                Message: {
                    Subject: {
                        Data: subject,
                        Charset: 'UTF-8',
                    },
                    Body: {
                        ...(htmlContent && {
                            Html: {
                                Data: htmlContent,
                                Charset: 'UTF-8',
                            },
                        }),
                        ...(textContent && {
                            Text: {
                                Data: textContent,
                                Charset: 'UTF-8',
                            },
                        }),
                    },
                },
            });

            const response = await sesClient.send(command);
            console.debug('SES message ID:', response.MessageId);
            return { messageId: response.MessageId || 'unknown' };
        }

        const raw = await buildRawSesMimeMessage({
            fromName: config.ses.senderName,
            fromEmail: config.ses.senderEmail,
            to: toAddresses,
            cc: ccAddresses,
            subject,
            htmlContent,
            textContent,
            attachments,
        });

        const rawCommand = new SendRawEmailCommand({
            Source: config.ses.senderEmail,
            RawMessage: { Data: new Uint8Array(raw) },
        });

        const rawResponse = await sesClient.send(rawCommand);
        console.debug('SES raw message ID:', rawResponse.MessageId);
        return { messageId: rawResponse.MessageId || 'unknown' };
    } catch (error: unknown) {
        console.error('SES sendEmail error:', error);

        const err = error as { name?: string; message?: string };
        if (err.name === 'MessageRejected') {
            console.error('SES rejected the message:', err.message);
        } else if (err.name === 'MailFromDomainNotVerifiedException') {
            console.error('SES sender email not verified:', config.ses.senderEmail);
        }

        return false;
    }
};
