import { z } from "zod";
import { toUSPhoneDigits } from "@shared/phone";
import { createCashOfferLead, updateCashOfferLeadWebhook } from "./db";

const CRM_WEBHOOK_TIMEOUT_MS = 10_000;

export const cashOfferLeadInputSchema = z.object({
  propertyAddress: z.string().trim().min(5, "Please enter a complete property address.").max(512),
  name: z.string().trim().min(2, "Please enter your full name.").max(160),
  phone: z.string().trim().transform(toUSPhoneDigits).refine((value) => /^\d{10}$/.test(value), "Please enter a valid 10-digit U.S. phone number."),
  email: z.string().trim().email("Please enter a valid email address.").max(320).optional().or(z.literal("")),
  timeline: z.string().trim().max(120).optional(),
  leadSource: z.string().trim().min(2).max(120).default("cash-offer-form"),
  consent: z.boolean().optional().default(false),
});

export type CashOfferLeadInput = z.infer<typeof cashOfferLeadInputSchema>;

type WebhookDelivery = {
  status: "not_configured" | "delivered" | "failed";
  error?: string;
};

function getWebhookUrl() {
  const configuredUrl = process.env.CRM_WEBHOOK_URL?.trim();
  if (!configuredUrl) return undefined;

  try {
    const url = new URL(configuredUrl);
    return url.protocol === "https:" ? url.toString() : undefined;
  } catch {
    return undefined;
  }
}

async function deliverLeadToWebhook(lead: { id: number } & CashOfferLeadInput): Promise<WebhookDelivery> {
  const webhookUrl = getWebhookUrl();
  if (!webhookUrl) {
    return { status: "not_configured" };
  }

  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), CRM_WEBHOOK_TIMEOUT_MS);

  try {
    const response = await fetch(webhookUrl, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        leadId: lead.id,
        propertyAddress: lead.propertyAddress,
        name: lead.name,
        phone: lead.phone,
        email: lead.email || undefined,
        timeline: lead.timeline || undefined,
        leadSource: lead.leadSource,
        consent: lead.consent,
        submittedAt: new Date().toISOString(),
      }),
      signal: controller.signal,
    });

    if (!response.ok) {
      return { status: "failed", error: `CRM webhook returned HTTP ${response.status}.` };
    }

    return { status: "delivered" };
  } catch (error) {
    const message = error instanceof Error ? error.message : "CRM webhook delivery failed.";
    return { status: "failed", error: message.slice(0, 1000) };
  } finally {
    clearTimeout(timeout);
  }
}

export async function submitCashOfferLead(input: CashOfferLeadInput) {
  const webhookConfigured = Boolean(getWebhookUrl());
  const lead = await createCashOfferLead({
    propertyAddress: input.propertyAddress,
    name: input.name,
    phone: input.phone,
    email: input.email || undefined,
    timeline: input.timeline || undefined,
    leadSource: input.leadSource,
    consent: input.consent,
    webhookStatus: webhookConfigured ? "pending" : "not_configured",
  });

  const delivery = await deliverLeadToWebhook({ id: lead.id, ...input });

  if (delivery.status !== "not_configured") {
    await updateCashOfferLeadWebhook(lead.id, {
      webhookStatus: delivery.status,
      webhookError: delivery.error ?? null,
      webhookAttemptedAt: new Date(),
    });
  }

  return {
    leadId: lead.id,
    webhookStatus: delivery.status,
  };
}
