import { Injectable, Logger } from '@nestjs/common';
import { Resend } from 'resend';

// Everything the invitation email needs to describe the meeting.
// The dates/times are already formatted by the caller so this service only
// has to build the email body.
export type SendMeetingInviteParams = {
  to: string[];
  meetingTitle: string;
  meetingDate?: string | null;
  timeRange?: string | null;
  location?: string | null;
  description?: string | null;
  ministryName: string;
};

@Injectable()
export class ResendMailMeetingsService {
  private readonly logger = new Logger(ResendMailMeetingsService.name);

  // Sends one invitation email to every guest of a scheduled meeting.
  // The Resend keys are read here (not in the constructor) so a missing key
  // only skips the email instead of stopping the whole application.
  async sendMeetingInviteEmail(
    params: SendMeetingInviteParams,
  ): Promise<string | null> {
    const apiKey = process.env.RESEND_API_KEY;
    const fromEmail = process.env.RESEND_FROM_EMAIL;

    if (!apiKey || !fromEmail) {
      this.logger.warn(
        'RESEND_API_KEY or RESEND_FROM_EMAIL is missing. Skip meeting invitation email.',
      );

      return null;
    }

    const recipients = Array.from(
      new Set(
        params.to
          .map((email) => email.trim().toLowerCase())
          .filter((email) => this.isValidEmail(email)),
      ),
    );

    if (recipients.length === 0) {
      this.logger.warn(
        'Meeting invitation has no valid guest email. Skip meeting invitation email.',
      );

      return null;
    }

    const subject = `Meeting Invitation - ${params.meetingTitle}`;

    try {
      const resend = new Resend(apiKey);

      const { data, error } = await resend.emails.send({
        from: fromEmail,
        to: recipients,
        subject,
        html: this.buildHtml(params),
        text: this.buildText(params),
      });

      if (error) {
        this.logger.error(
          `Failed to send meeting invitation email: ${error.message}`,
        );

        return null;
      }

      this.logger.log(`Meeting invitation email sent. id=${data?.id || '-'}`);

      return data?.id ? String(data.id) : null;
    } catch (error) {
      this.logger.error(
        'Unexpected error while sending meeting invitation email.',
        error,
      );

      return null;
    }
  }

  private buildHtml(params: SendMeetingInviteParams): string {
    return `
      <div style="font-family: Arial, sans-serif; line-height: 1.6; color: #111827;">
        <h2 style="margin: 0 0 14px; color: #1F6DB2;">
          Meeting Invitation
        </h2>

        <p>
          <strong>${this.escapeHtml(params.ministryName)}</strong>
          invited you to the meeting below.
        </p>

        <table style="border-collapse: collapse; width: 100%; margin-top: 14px;">
          <tbody>
            ${this.buildRow('Meeting', params.meetingTitle)}
            ${this.buildRow('Date', params.meetingDate)}
            ${this.buildRow('Time', params.timeRange)}
            ${this.buildRow('Location', params.location)}
            ${this.buildRow('Invited By', params.ministryName)}
          </tbody>
        </table>

        ${
          params.description?.trim()
            ? `
              <div style="margin-top: 18px;">
                <strong>Description:</strong>
                <div style="margin-top: 8px; padding: 12px; background: #F9FAFB; border: 1px solid #E5E7EB; border-radius: 8px;">
                  ${this.renderEditorHtml(params.description)}
                </div>
              </div>
            `
            : ''
        }

        <p style="margin-top: 20px; color: #6B7280; font-size: 12px;">
          This is an automatic notification from G-PSF MIS.
        </p>
      </div>
    `;
  }

  private buildRow(label: string, value?: string | null): string {
    return `
      <tr>
        <td style="padding: 8px; border: 1px solid #E5E7EB; width: 180px;">
          <strong>${this.escapeHtml(label)}</strong>
        </td>
        <td style="padding: 8px; border: 1px solid #E5E7EB;">
          ${this.escapeHtml(value?.trim() || '-')}
        </td>
      </tr>
    `;
  }

  private buildText(params: SendMeetingInviteParams): string {
    return [
      'Meeting Invitation',
      '',
      `Meeting: ${params.meetingTitle}`,
      `Date: ${params.meetingDate?.trim() || '-'}`,
      `Time: ${params.timeRange?.trim() || '-'}`,
      `Location: ${params.location?.trim() || '-'}`,
      `Invited By: ${params.ministryName}`,
      '',
      `Description: ${this.stripHtml(params.description || '-')}`,
    ].join('\n');
  }

  private renderEditorHtml(value?: string | null): string {
    if (!value?.trim()) {
      return '-';
    }

    return value
      .replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '')
      .replace(/on\w+="[^"]*"/gi, '')
      .replace(/on\w+='[^']*'/gi, '')
      .replace(/javascript:/gi, '');
  }

  private stripHtml(value: string): string {
    return value
      .replace(/<br\s*\/?>/gi, '\n')
      .replace(/<\/p>/gi, '\n')
      .replace(/<\/div>/gi, '\n')
      .replace(/<[^>]*>/g, ' ')
      .replace(/&nbsp;/gi, ' ')
      .replace(/&amp;/gi, '&')
      .replace(/&lt;/gi, '<')
      .replace(/&gt;/gi, '>')
      .replace(/\s+/g, ' ')
      .trim();
  }

  private escapeHtml(value: string): string {
    return value
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#039;');
  }

  private isValidEmail(value?: string | null): value is string {
    if (!value) {
      return false;
    }

    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
  }
}
