import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import nodemailer, {
  type SendMailOptions,
  type Transporter,
} from 'nodemailer';

type TemplateSection = {
  label: string;
  value: string;
};

type TemplatePayload = {
  subject: string;
  preheader: string;
  headline: string;
  intro: string;
  message: string[];
  sections?: TemplateSection[];
  actionLabel?: string;
  actionUrl?: string | null;
  closing?: string;
};

type StoreRegistrationEmailArgs = {
  to: string;
  shopName: string;
  merchantEmail: string;
  merchantPhone?: string | null;
  planCode?: string | null;
  portalUrl?: string | null;
};

type ShopApprovedEmailArgs = {
  to: string;
  recipientName?: string | null;
  shopName: string;
  city?: string | null;
  portalUrl?: string | null;
};

type CouponUnlockedEmailArgs = {
  to: string;
  recipientName?: string | null;
  couponTitle: string;
  shopName: string;
  appUrl?: string | null;
};

@Injectable()
export class MailService {
  private readonly logger = new Logger(MailService.name);
  private transporter: Transporter | null = null;

  constructor(private readonly config: ConfigService) {}

  async sendStoreRegistrationReceived(
    args: StoreRegistrationEmailArgs,
  ): Promise<boolean> {
    return this.sendTemplatedMail(args.to, {
      subject: `Welcome to the Cashi Family, ${args.shopName}`,
      preheader:
        'Your merchant account has been created and is now under review.',
      headline: 'Welcome to the Cashi Family',
      intro: `Thank you for registering ${args.shopName} with Cashi.`,
      message: [
        'Your merchant account has been created successfully and your business is now under review.',
        'Once the listing is approved, we will send you another email confirming that your business is live on Cashi.',
        'For security, we do not include your password in email. Please use the password you created during registration to sign in.',
      ],
      sections: [
        { label: 'Business name', value: args.shopName },
        { label: 'Registered email', value: args.merchantEmail },
        ...(args.merchantPhone
          ? [{ label: 'Registered mobile', value: args.merchantPhone }]
          : []),
        ...(args.planCode
          ? [{ label: 'Selected plan', value: args.planCode }]
          : []),
      ],
      actionLabel: args.portalUrl ? 'Open Merchant Portal' : undefined,
      actionUrl: args.portalUrl,
      closing:
        'If you need any help with onboarding, just reply to this email and our team will assist you.',
    });
  }

  async sendShopApproved(args: ShopApprovedEmailArgs): Promise<boolean> {
    const greetingTarget = args.recipientName?.trim() || args.shopName;
    return this.sendTemplatedMail(args.to, {
      subject: `${args.shopName} is now live on Cashi`,
      preheader:
        'Your business listing has been approved and is now visible on Cashi.',
      headline: 'Business listed on Cashi',
      intro: `Dear ${greetingTarget},`,
      message: [
        `We are pleased to inform you that ${args.shopName} has been approved and is now live on Cashi.`,
        'Customers can now discover your business and engage with your offers on the platform.',
        'Please review your business details and keep your storefront, coupons, and loyalty offers updated for the best results.',
      ],
      sections: [
        { label: 'Business name', value: args.shopName },
        ...(args.city ? [{ label: 'Location', value: args.city }] : []),
        { label: 'Listing status', value: 'Approved and live' },
      ],
      actionLabel: args.portalUrl ? 'Manage Your Business' : undefined,
      actionUrl: args.portalUrl,
      closing:
        'Thank you for growing with the Cashi Family. We are excited to have your business on the platform.',
    });
  }

  async sendCouponUnlocked(args: CouponUnlockedEmailArgs): Promise<boolean> {
    const greetingTarget = args.recipientName?.trim() || 'Member';
    return this.sendTemplatedMail(args.to, {
      subject: 'A new Cashi coupon has been unlocked for you',
      preheader:
        'A new reward coupon is now available based on your recent purchase.',
      headline: 'Coupon unlocked',
      intro: `Dear ${greetingTarget},`,
      message: [
        `Good news. A new coupon has been unlocked for you after your recent purchase at ${args.shopName}.`,
        `Your newly unlocked reward is: ${args.couponTitle}.`,
        'Open Cashi to view the coupon details and redeem it before it expires.',
      ],
      sections: [
        { label: 'Unlocked coupon', value: args.couponTitle },
        { label: 'Issued by', value: args.shopName },
      ],
      actionLabel: args.appUrl ? 'Open Cashi' : undefined,
      actionUrl: args.appUrl,
      closing:
        'Thank you for being part of the Cashi Family. We look forward to bringing you more rewards.',
    });
  }

  private async sendTemplatedMail(
    to: string,
    payload: TemplatePayload,
  ): Promise<boolean> {
    const normalizedTo = String(to ?? '').trim().toLowerCase();
    if (!normalizedTo) return false;

    const transport = this.getTransporter();
    if (!transport) return false;

    const html = this.renderHtml(payload);
    const text = this.renderText(payload);
    const fromMail = this.getString('mail.fromMail');
    const fromName = this.getString('mail.fromName') || 'Cashi Family';
    const replyMail =
      this.getString('mail.replyMail') || this.getString('mail.supportEmail');
    const replyName = this.getString('mail.replyName') || fromName;

    const options: SendMailOptions = {
      from: fromMail ? `"${fromName}" <${fromMail}>` : undefined,
      to: normalizedTo,
      subject: payload.subject,
      html,
      text,
      ...(replyMail
        ? {
            replyTo: `"${replyName}" <${replyMail}>`,
          }
        : {}),
    };

    await transport.sendMail(options);
    this.logger.log(`Mail sent to ${normalizedTo}: ${payload.subject}`);
    return true;
  }

  private getTransporter(): Transporter | null {
    if (this.transporter) return this.transporter;

    const enabled = this.config.get<boolean>('mail.enabled') ?? false;
    if (!enabled) {
      this.logger.warn(
        'Mail sending is disabled. Set MAIL_ENABLED=true to enable SMTP delivery.',
      );
      return null;
    }

    const host = this.getString('mail.host');
    const port = this.config.get<number>('mail.port') ?? 25;
    const user = this.getString('mail.user');
    const pass = this.getString('mail.pass');

    if (!host || !user || !pass) {
      this.logger.warn(
        'SMTP is not fully configured. Missing SMTP_HOST, SMTP_USER, or SMTP_PASS.',
      );
      return null;
    }

    this.transporter = nodemailer.createTransport({
      host,
      port,
      secure: this.config.get<boolean>('mail.secure') ?? false,
      requireTLS: this.config.get<boolean>('mail.requireTls') ?? false,
      auth: {
        user,
        pass,
      },
    });

    return this.transporter;
  }

  private renderHtml(payload: TemplatePayload): string {
    const supportEmail =
      this.getString('mail.supportEmail') ||
      this.getString('mail.replyMail') ||
      this.getString('mail.fromMail') ||
      'care@cashi.in';
    const brandName = this.getString('mail.brandName') || 'Cashi Family';

    const messageHtml = payload.message
      .map(
        (line) =>
          `<p style="margin:0 0 14px;color:#374151;font-size:15px;line-height:1.7;">${this.escapeHtml(line)}</p>`,
      )
      .join('');

    const sectionHtml = (payload.sections ?? [])
      .map(
        (section) =>
          `<tr>
            <td style="padding:10px 0;border-bottom:1px solid #e5e7eb;font-size:13px;color:#6b7280;">${this.escapeHtml(section.label)}</td>
            <td style="padding:10px 0;border-bottom:1px solid #e5e7eb;font-size:14px;color:#111827;font-weight:600;text-align:right;">${this.escapeHtml(section.value)}</td>
          </tr>`,
      )
      .join('');

    const actionHtml =
      payload.actionLabel && payload.actionUrl
        ? `<div style="margin:28px 0 8px;">
            <a href="${this.escapeHtml(payload.actionUrl)}" style="display:inline-block;padding:12px 22px;border-radius:10px;background:#111827;color:#ffffff;text-decoration:none;font-size:14px;font-weight:700;">
              ${this.escapeHtml(payload.actionLabel)}
            </a>
          </div>`
        : '';

    return `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>${this.escapeHtml(payload.subject)}</title>
  </head>
  <body style="margin:0;padding:24px;background:#f3f4f6;font-family:Arial,sans-serif;">
    <div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;">
      ${this.escapeHtml(payload.preheader)}
    </div>
    <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:680px;margin:0 auto;background:#ffffff;border-radius:18px;overflow:hidden;">
      <tr>
        <td style="padding:28px 32px;background:#111827;color:#ffffff;">
          <div style="font-size:12px;letter-spacing:0.12em;text-transform:uppercase;opacity:0.75;">${this.escapeHtml(brandName)}</div>
          <div style="margin-top:10px;font-size:28px;font-weight:800;line-height:1.2;">${this.escapeHtml(payload.headline)}</div>
          <div style="margin-top:10px;font-size:15px;line-height:1.6;color:#d1d5db;">${this.escapeHtml(payload.intro)}</div>
        </td>
      </tr>
      <tr>
        <td style="padding:32px;">
          ${messageHtml}
          ${
            sectionHtml
              ? `<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="margin:24px 0 6px;">${sectionHtml}</table>`
              : ''
          }
          ${actionHtml}
          ${
            payload.closing
              ? `<p style="margin:28px 0 0;color:#374151;font-size:15px;line-height:1.7;">${this.escapeHtml(payload.closing)}</p>`
              : ''
          }
        </td>
      </tr>
      <tr>
        <td style="padding:24px 32px;background:#f9fafb;border-top:1px solid #e5e7eb;color:#6b7280;font-size:13px;line-height:1.7;">
          <div style="font-weight:700;color:#111827;">Team Cashi</div>
          <div style="margin-top:6px;">For support, write to <a href="mailto:${this.escapeHtml(supportEmail)}" style="color:#111827;">${this.escapeHtml(supportEmail)}</a></div>
        </td>
      </tr>
    </table>
  </body>
</html>`;
  }

  private renderText(payload: TemplatePayload): string {
    const supportEmail =
      this.getString('mail.supportEmail') ||
      this.getString('mail.replyMail') ||
      this.getString('mail.fromMail') ||
      'care@cashi.in';
    const brandName = this.getString('mail.brandName') || 'Cashi Family';
    const sectionLines = (payload.sections ?? []).map(
      (section) => `${section.label}: ${section.value}`,
    );

    return [
      brandName,
      '',
      payload.headline,
      payload.intro,
      '',
      ...payload.message,
      ...(sectionLines.length ? ['', ...sectionLines] : []),
      ...(payload.actionLabel && payload.actionUrl
        ? ['', `${payload.actionLabel}: ${payload.actionUrl}`]
        : []),
      ...(payload.closing ? ['', payload.closing] : []),
      '',
      `Support: ${supportEmail}`,
    ].join('\n');
  }

  private getString(path: string): string {
    return String(this.config.get<string>(path) ?? '').trim();
  }

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