/**
 * CRM-owned emails for captured website inquiries.
 *
 * The marketing website dual-writes every inquiry into `website_submissions`
 * (capture-only). At cutover, email ownership moves from the website to the
 * CRM: when the per-port flag `website_intake_email_enabled` is ON, the CRM
 * sends the registrant confirmation + staff alert for each fresh submission,
 * reusing the existing branded inquiry templates. Default OFF, so the website
 * keeps sending until the flip and we never double-send.
 *
 * Sends are inline + fire-and-forget (the caller wraps in `void ...catch`):
 * a send failure must never 500 the public capture endpoint. Dedup is handled
 * upstream by invoking this only on a fresh (non-redelivered) insert.
 */

import { and, eq, isNull, or } from 'drizzle-orm';

import { db } from '@/lib/db';
import { ports } from '@/lib/db/schema/ports';
import { systemSettings } from '@/lib/db/schema/system';
import { sendEmail } from '@/lib/email';
import { getBrandingShell } from '@/lib/email/branding-resolver';
import { resolveSubject } from '@/lib/email/resolve-subject';
import { inquiryClientConfirmation } from '@/lib/email/templates/inquiry-client-confirmation';
import { inquirySalesNotification } from '@/lib/email/templates/inquiry-sales-notification';
import {
  residentialClientConfirmation,
  residentialSalesAlert,
} from '@/lib/email/templates/residential-inquiry';
import { contactFormSalesAlert } from '@/lib/email/templates/contact-form-alert';
import { contactFormClientConfirmation } from '@/lib/email/templates/contact-form-client-confirmation';
import { resolveNotificationRecipients } from '@/lib/services/notification-recipients';
import { extractInquiryFields } from '@/lib/services/website-intake-fields';
import { createNotification } from '@/lib/services/notifications.service';
import { findUsersWithInterestsPermission } from '@/lib/services/inquiry-notifications.service';
import { logger } from '@/lib/logger';

/**
 * Per-port gate. Default OFF (no row -> disabled), matching the
 * `invoices_module_enabled` pattern.
 */
export async function isWebsiteIntakeEmailEnabled(portId: string): Promise<boolean> {
  const row = await db
    .select({ value: systemSettings.value })
    .from(systemSettings)
    .where(
      and(
        eq(systemSettings.key, 'website_intake_email_enabled'),
        or(eq(systemSettings.portId, portId), isNull(systemSettings.portId)),
      ),
    )
    .limit(1);
  return row[0]?.value === true;
}

/**
 * Resolve staff-alert recipients for a port. Delegates to the shared resolver,
 * which expands the structured {emails,userIds,roleIds,everyone} config (or a
 * legacy email array) into concrete addresses, falling back to
 * `inquiry_contact_email`. Returns [] when nothing is configured.
 */
async function resolveRecipients(portId: string, primaryKey: string): Promise<string[]> {
  return resolveNotificationRecipients(portId, primaryKey);
}

export interface WebsiteSubmissionEmailInput {
  portId: string;
  portSlug: string;
  kind: string;
  submissionId: string;
  payload: Record<string, unknown>;
}

export async function sendWebsiteSubmissionEmails(
  input: WebsiteSubmissionEmailInput,
): Promise<void> {
  const { portId, portSlug, kind, payload } = input;
  const fields = extractInquiryFields(payload);

  const [branding, portRow] = await Promise.all([
    getBrandingShell(portId),
    db.select({ name: ports.name }).from(ports).where(eq(ports.id, portId)).limit(1),
  ]);
  // Client-facing copy uses the PUBLIC port name ("Port Nimara"), never the CRM
  // appName ("Port Nimara CRM") which is reserved for internal/staff surfaces.
  const portName = portRow[0]?.name ?? 'Port Nimara';

  // Public reply-to shown to clients in confirmation emails ("reach out to us
  // at ..."). Admin-configurable per category via system_settings; contact-form
  // enquiries default to the hello@ general inbox, berth + residence to sales@.
  // Never the noreply From address.
  const contactEmailKey =
    kind === 'contact_form' ? 'contact_form_contact_email' : 'inquiry_contact_email';
  const contactEmailDefault =
    kind === 'contact_form' ? 'hello@portnimara.com' : 'sales@portnimara.com';
  const [contactRow] = await db
    .select({ value: systemSettings.value })
    .from(systemSettings)
    .where(
      and(
        eq(systemSettings.key, contactEmailKey),
        or(eq(systemSettings.portId, portId), isNull(systemSettings.portId)),
      ),
    )
    .limit(1);
  const contactEmail =
    typeof contactRow?.value === 'string' && contactRow.value.trim()
      ? contactRow.value.trim()
      : contactEmailDefault;
  // No interest/client row exists for a raw submission, so link to the
  // dashboard rather than a (nonexistent) entity detail page.
  const crmUrl = `${process.env.APP_URL ?? ''}/${portSlug}`;

  if (kind === 'berth_inquiry') {
    if (fields.email) {
      const confirmation = await inquiryClientConfirmation(
        {
          firstName: fields.firstName,
          mooringNumber: fields.mooringNumber,
          contactEmail,
          portName,
        },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'inquiry_client_confirmation',
        portId,
        fallback: confirmation.subject,
        tokens: {
          portName,
          recipientName: fields.firstName,
          mooringNumber: fields.mooringNumber ?? '',
        },
      });
      await sendEmail(
        fields.email,
        subject,
        confirmation.html,
        undefined,
        confirmation.text,
        portId,
        undefined,
        undefined,
        undefined,
        contactEmail,
      );
    }

    const recipients = await resolveRecipients(portId, 'inquiry_notification_recipients');
    if (recipients.length > 0) {
      const alert = await inquirySalesNotification(
        {
          fullName: fields.fullName,
          email: fields.email,
          phone: fields.phone,
          mooringNumber: fields.mooringNumber,
          crmUrl,
          portName,
        },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'inquiry_sales_notification',
        portId,
        fallback: alert.subject,
        tokens: {
          portName,
          clientName: fields.fullName,
          mooringNumber: fields.mooringNumber ?? '',
          email: fields.email,
        },
      });
      await sendEmail(recipients, subject, alert.html, undefined, alert.text, portId);
    }
    return;
  }

  if (kind === 'residence_inquiry') {
    if (fields.email) {
      const confirmation = await residentialClientConfirmation(
        {
          firstName: fields.firstName,
          contactEmail,
          residenceTypes: fields.residenceTypes,
          portName,
        },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'residential_inquiry_client_confirmation',
        portId,
        fallback: confirmation.subject,
        tokens: { portName, recipientName: fields.firstName },
      });
      await sendEmail(
        fields.email,
        subject,
        confirmation.html,
        undefined,
        confirmation.text,
        portId,
        undefined,
        undefined,
        undefined,
        contactEmail,
      );
    }

    const recipients = await resolveRecipients(portId, 'residential_notification_recipients');
    if (recipients.length > 0) {
      const alert = await residentialSalesAlert(
        {
          fullName: fields.fullName,
          email: fields.email,
          phone: fields.phone,
          residenceTypes: fields.residenceTypes,
          preferredContactMethod: fields.preferredContact ?? undefined,
          placeOfResidence: fields.placeOfResidence ?? undefined,
          notes: fields.comments ?? undefined,
          portName,
        },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'residential_inquiry_sales_alert',
        portId,
        fallback: alert.subject,
        tokens: { portName, clientName: fields.fullName, email: fields.email, phone: fields.phone },
      });
      await sendEmail(recipients, subject, alert.html, undefined, alert.text, portId);
    }
    return;
  }

  if (kind === 'contact_form') {
    // Client confirmation: a "thanks, we received your message" auto-reply.
    // This is CRM-only (the website never sent one), so there is no
    // double-send risk; it simply starts once the port flips the flag on.
    if (fields.email) {
      const confirmation = await contactFormClientConfirmation(
        { firstName: fields.firstName, contactEmail, portName },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'contact_form_client_confirmation',
        portId,
        fallback: confirmation.subject,
        tokens: { portName, recipientName: fields.firstName },
      });
      await sendEmail(
        fields.email,
        subject,
        confirmation.html,
        undefined,
        confirmation.text,
        portId,
        undefined,
        undefined,
        undefined,
        contactEmail,
      );
    }

    // Contact-form alerts go to their own recipient list (the website routed
    // them to hello@ separately from berth alerts). Falls back to
    // inquiry_notification_recipients only via the shared resolver's
    // inquiry_contact_email fallback when unset.
    const recipients = await resolveRecipients(portId, 'contact_notification_recipients');
    if (recipients.length > 0) {
      const alert = await contactFormSalesAlert(
        {
          fullName: fields.fullName,
          email: fields.email,
          interestType: fields.interestType,
          comments: fields.comments,
          crmDeepLink: crmUrl,
          portName,
        },
        { branding },
      );
      const subject = await resolveSubject({
        key: 'contact_form_sales_alert',
        portId,
        fallback: alert.subject,
        tokens: { portName, clientName: fields.fullName, email: fields.email },
      });
      await sendEmail(recipients, subject, alert.html, undefined, undefined, portId);
    }
    return;
  }

  logger.warn({ kind }, 'website-intake email: unknown submission kind, no email sent');
}

const KIND_LABEL: Record<string, string> = {
  berth_inquiry: 'berth inquiry',
  residence_inquiry: 'residential inquiry',
  contact_form: 'contact form',
};

/**
 * In-app (bell) notifications for a captured website submission. Fires on
 * every fresh capture, independent of the email-ownership flag, so reps see
 * incoming website inquiries in the CRM inbox even before email cutover.
 * Fire-and-forget; deduped per submission.
 */
export async function notifyWebsiteSubmissionInApp(input: {
  portId: string;
  portSlug: string;
  kind: string;
  submissionId: string;
  payload: Record<string, unknown>;
}): Promise<void> {
  const { portId, portSlug, kind, submissionId, payload } = input;
  const userIds = await findUsersWithInterestsPermission(portId);
  if (userIds.length === 0) return;

  const fields = extractInquiryFields(payload);
  const who = fields.fullName || 'A visitor';
  const label = KIND_LABEL[kind] ?? 'inquiry';
  const description = `${who} submitted a ${label} via the website`;
  const link = `/${portSlug}/inbox`;

  await Promise.allSettled(
    userIds.map((userId) =>
      createNotification({
        portId,
        userId,
        type: 'new_registration',
        title: 'New website inquiry',
        description,
        link,
        entityType: 'website_submission',
        entityId: submissionId,
        dedupeKey: `website-submission-${submissionId}`,
      }),
    ),
  );
}
