import "server-only";
import { db } from "./db";
import { getSettings } from "./settings";
import { formatMoney, fmtDate, dateRange } from "./utils";

/**
 * AWS SES email layer.
 * Config precedence: admin System settings (ses.*) → environment variables →
 * disabled (every send is logged as SKIPPED so flows never break).
 */

export type SesConfig = {
  region: string;
  fromEmail: string;
  fromName: string;
  accessKeyId?: string;
  secretAccessKey?: string;
  source: "settings" | "env";
};

export async function getSesConfig(): Promise<SesConfig | null> {
  const s = await getSettings(["ses.region", "ses.fromEmail", "ses.fromName", "ses.accessKeyId", "ses.secretAccessKey"]);
  if (s["ses.fromEmail"]) {
    return {
      region: s["ses.region"] || "ap-south-1",
      fromEmail: s["ses.fromEmail"],
      fromName: s["ses.fromName"] || "Confexe",
      accessKeyId: s["ses.accessKeyId"] || undefined,
      secretAccessKey: s["ses.secretAccessKey"] || undefined,
      source: "settings",
    };
  }
  if (process.env.SES_FROM_EMAIL) {
    return {
      region: process.env.SES_REGION || "ap-south-1",
      fromEmail: process.env.SES_FROM_EMAIL,
      fromName: process.env.SES_FROM_NAME || "Confexe",
      source: "env", // credentials via SDK default chain (env / EC2 instance role)
    };
  }
  return null;
}

export async function getBaseUrl(): Promise<string> {
  const s = await getSettings(["platform.baseUrl"]);
  return (s["platform.baseUrl"] || process.env.BASE_URL || "http://localhost:3300").replace(/\/$/, "");
}

/** Branded HTML shell shared by every trigger. */
function layout(opts: { title: string; bodyHtml: string; accent?: string; footer?: string }): string {
  const accent = opts.accent ?? "#6366f1";
  return `<!doctype html><html><body style="margin:0;background:#eef1fb;font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;padding:24px 12px;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0"><tr><td align="center">
  <table role="presentation" width="560" cellpadding="0" cellspacing="0" style="max-width:560px;width:100%;background:#ffffff;border-radius:16px;overflow:hidden;box-shadow:0 8px 32px rgba(80,90,180,.12);">
    <tr><td style="background:${accent};padding:20px 28px;">
      <div style="color:#ffffff;font-size:18px;font-weight:800;">${opts.title}</div>
    </td></tr>
    <tr><td style="padding:28px;color:#1f2a44;font-size:15px;line-height:1.6;">${opts.bodyHtml}</td></tr>
    <tr><td style="padding:16px 28px;border-top:1px solid #eef1fb;color:#8fa0b8;font-size:12px;">
      ${opts.footer ?? "Sent by Confexe — the conference operating system."}
    </td></tr>
  </table></td></tr></table></body></html>`;
}

const btnHtml = (href: string, label: string, accent = "#6366f1") =>
  `<a href="${href}" style="display:inline-block;background:${accent};color:#ffffff;text-decoration:none;font-weight:700;padding:11px 22px;border-radius:10px;margin:8px 0;">${label}</a>`;

/** Core send. Never throws — logs SENT / FAILED / SKIPPED to EmailLog. */
export async function sendEmail(opts: {
  to: string;
  subject: string;
  html: string;
  template: string;
  conferenceId?: string;
}): Promise<"SENT" | "FAILED" | "SKIPPED"> {
  const log = async (status: string, error?: string) => {
    try {
      await db.emailLog.create({
        data: { to: opts.to, subject: opts.subject, template: opts.template, status, error: error?.slice(0, 300), conferenceId: opts.conferenceId },
      });
    } catch { /* logging must never break the flow */ }
  };

  try {
    const config = await getSesConfig();
    if (!config) {
      await log("SKIPPED", "SES not configured (admin → System settings)");
      return "SKIPPED";
    }
    const { SESv2Client, SendEmailCommand } = await import("@aws-sdk/client-sesv2");
    const client = new SESv2Client({
      region: config.region,
      ...(config.accessKeyId && config.secretAccessKey
        ? { credentials: { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey } }
        : {}),
    });
    await client.send(
      new SendEmailCommand({
        FromEmailAddress: `${config.fromName} <${config.fromEmail}>`,
        Destination: { ToAddresses: [opts.to] },
        Content: {
          Simple: {
            Subject: { Data: opts.subject, Charset: "UTF-8" },
            Body: { Html: { Data: opts.html, Charset: "UTF-8" } },
          },
        },
      })
    );
    await log("SENT");
    return "SENT";
  } catch (e) {
    await log("FAILED", (e as Error).message);
    return "FAILED";
  }
}

// ── Triggers ──────────────────────────────────────────────

export async function sendRegistrationConfirmedEmail(registrationId: string) {
  const reg = await db.registration.findUnique({
    where: { id: registrationId },
    include: { conference: true, ticketType: true },
  });
  if (!reg) return;
  const base = await getBaseUrl();
  const c = reg.conference;
  const ticketUrl = `${base}/c/${c.slug}/ticket/${reg.regCode}`;
  await sendEmail({
    to: reg.email,
    subject: `🎟️ You're in! Ticket for ${c.name}`,
    template: "registration_confirmed",
    conferenceId: c.id,
    html: layout({
      title: c.name,
      accent: c.primaryColor,
      bodyHtml: `
        <p>Hi ${reg.name},</p>
        <p>Your registration is <strong>confirmed</strong>. Here are your details:</p>
        <table style="font-size:14px;color:#33415c;line-height:1.9;">
          <tr><td style="color:#8fa0b8;padding-right:16px;">Registration ID</td><td><strong style="font-family:monospace;">${reg.regCode}</strong></td></tr>
          <tr><td style="color:#8fa0b8;">Pass</td><td>${reg.ticketType.name} · ${formatMoney(reg.amount)}</td></tr>
          <tr><td style="color:#8fa0b8;">Dates</td><td>${dateRange(c.startAt, c.endAt)}</td></tr>
          <tr><td style="color:#8fa0b8;">Venue</td><td>${c.type === "VIRTUAL" ? "Online" : `${c.venueName ?? ""}${c.city ? ", " + c.city : ""}`}</td></tr>
        </table>
        <p>${btnHtml(ticketUrl, "View my QR ticket", c.primaryColor)}</p>
        <p style="color:#61708a;font-size:13px;">Show the QR code at the check-in desk. See the full schedule at <a href="${base}/c/${c.slug}/schedule">${base.replace(/^https?:\/\//, "")}/c/${c.slug}/schedule</a>.</p>`,
    }),
  });
}

export async function sendVolunteerWelcomeEmail(opts: { email: string; name: string; conferenceId: string; tempPassword: string | null; areas: string[] }) {
  const conf = await db.conference.findUnique({ where: { id: opts.conferenceId }, select: { name: true, primaryColor: true } });
  if (!conf) return;
  const base = await getBaseUrl();
  await sendEmail({
    to: opts.email,
    subject: `🙋 You're a volunteer at ${conf.name}`,
    template: "volunteer_welcome",
    conferenceId: opts.conferenceId,
    html: layout({
      title: conf.name,
      accent: conf.primaryColor,
      bodyHtml: `
        <p>Hi ${opts.name},</p>
        <p>You've been added to the volunteer team for <strong>${conf.name}</strong>.</p>
        <p><strong>Your duties:</strong> ${opts.areas.length ? opts.areas.join(", ") : "to be assigned"}</p>
        ${opts.tempPassword
          ? `<p>A login was created for you:<br/>Email: <strong>${opts.email}</strong><br/>Temporary password: <strong style="font-family:monospace;">${opts.tempPassword}</strong></p>
             <p style="color:#61708a;font-size:13px;">Please sign in and keep your password safe.</p>`
          : `<p>Sign in with your existing Confexe account to see your assignments.</p>`}
        <p>${btnHtml(`${base}/login`, "Open my volunteer dashboard", conf.primaryColor)}</p>`,
    }),
  });
}

export async function sendSubmissionDecisionEmail(submissionId: string) {
  const sub = await db.submission.findUnique({
    where: { id: submissionId },
    include: { conference: true, user: true },
  });
  if (!sub) return;
  const base = await getBaseUrl();
  const verdict =
    sub.status === "ACCEPTED" ? { subj: "🎉 Accepted", line: "Congratulations — your submission has been <strong>accepted</strong>!" }
    : sub.status === "REJECTED" ? { subj: "Submission decision", line: "We're sorry — your submission was <strong>not accepted</strong> this time." }
    : { subj: "Revision requested", line: "The committee has requested a <strong>revision</strong> of your submission." };
  await sendEmail({
    to: sub.user.email,
    subject: `${verdict.subj}: ${sub.title}`,
    template: "submission_decision",
    conferenceId: sub.conferenceId,
    html: layout({
      title: sub.conference.name,
      accent: sub.conference.primaryColor,
      bodyHtml: `
        <p>Hi ${sub.user.name},</p>
        <p>${verdict.line}</p>
        <p style="border-left:3px solid ${sub.conference.primaryColor};padding-left:12px;color:#33415c;"><strong>${sub.title}</strong><br/><span style="color:#8fa0b8;font-size:13px;">${sub.category}</span></p>
        <p>${btnHtml(`${base}/me/submissions`, "View my submissions", sub.conference.primaryColor)}</p>`,
    }),
  });
}

export async function sendCertificateEmail(certId: string) {
  const cert = await db.certificate.findUnique({ where: { certId }, include: { conference: true } });
  if (!cert) return;
  const base = await getBaseUrl();
  const url = `${base}/verify/${cert.certId}`;
  await sendEmail({
    to: cert.recipientEmail,
    subject: `🏅 Your certificate from ${cert.conference.name}`,
    template: "certificate_issued",
    conferenceId: cert.conferenceId,
    html: layout({
      title: cert.conference.name,
      accent: cert.conference.primaryColor,
      bodyHtml: `
        <p>Hi ${cert.recipientName},</p>
        <p>Your <strong>${cert.type.toLowerCase()}</strong> certificate is ready. It carries a unique ID (<span style="font-family:monospace;">${cert.certId}</span>) and can be verified by anyone at the link below.</p>
        <p>${btnHtml(url, "View & download certificate", cert.conference.primaryColor)}</p>
        <p style="color:#61708a;font-size:13px;">Issued ${fmtDate(cert.issuedAt)} · printable A4 with QR verification.</p>`,
    }),
  });
}

export async function sendReviewerAssignedEmail(reviewerEmail: string, conferenceId: string) {
  const conf = await db.conference.findUnique({ where: { id: conferenceId }, select: { name: true, primaryColor: true } });
  if (!conf) return;
  const base = await getBaseUrl();
  await sendEmail({
    to: reviewerEmail,
    subject: `📄 New review assignment — ${conf.name}`,
    template: "reviewer_assigned",
    conferenceId,
    html: layout({
      title: conf.name,
      accent: conf.primaryColor,
      bodyHtml: `
        <p>A paper has been assigned to you for review.</p>
        <p>${btnHtml(`${base}/me/reviews`, "Open my review inbox", conf.primaryColor)}</p>
        <p style="color:#61708a;font-size:13px;">Reviews are single-blind — authors will not see your name.</p>`,
    }),
  });
}

/** Announcement blast to confirmed registrants (capped, best-effort). */
export async function sendAnnouncementBlast(conferenceId: string, title: string, body: string) {
  const conf = await db.conference.findUnique({ where: { id: conferenceId }, select: { name: true, slug: true, primaryColor: true } });
  if (!conf) return;
  const regs = await db.registration.findMany({
    where: { conferenceId, status: "CONFIRMED" },
    select: { email: true, name: true },
    distinct: ["email"],
    take: 200, // safety cap for the demo-scale blast
  });
  const base = await getBaseUrl();
  await Promise.allSettled(
    regs.map((r) =>
      sendEmail({
        to: r.email,
        subject: `📢 ${conf.name}: ${title}`,
        template: "announcement",
        conferenceId,
        html: layout({
          title: conf.name,
          accent: conf.primaryColor,
          bodyHtml: `
            <p>Hi ${r.name},</p>
            <p><strong>${title}</strong></p>
            <p>${body || ""}</p>
            <p>${btnHtml(`${base}/c/${conf.slug}`, "Open conference site", conf.primaryColor)}</p>`,
        }),
      })
    )
  );
}

export async function sendWelcomeEmail(email: string, name: string, organizer: boolean) {
  const base = await getBaseUrl();
  await sendEmail({
    to: email,
    subject: "Welcome to Confexe 👋",
    template: "welcome",
    html: layout({
      title: "Welcome to Confexe",
      bodyHtml: `
        <p>Hi ${name},</p>
        <p>Your account is ready. ${organizer ? "Create your first conference and get a public website, registration engine, agenda builder and check-in tools out of the box." : "Browse conferences, register in a couple of clicks, and keep your tickets and certificates in one place."}</p>
        <p>${btnHtml(base + (organizer ? "/dashboard" : "/me"), organizer ? "Open my dashboard" : "Open my conferences")}</p>`,
    }),
  });
}
