import { DeliveryStatus } from "@prisma/client";

export type OutboundMessageRequest = {
  tenantId: string;
  channelId: string;
  channelProvider: string;
  phoneNumberId: string | null;
  to: string;
  content: string;
  messageId: string;
};

export type OutboundMessageResult = {
  success: boolean;
  provider: string;
  deliveryStatus: DeliveryStatus;
  providerMessageId?: string | null;
  failureReason?: string;
};

type MetaResponse = {
  messages?: Array<{ id?: string }>;
  error?: {
    message?: string;
  };
};

function normalizeProvider(provider: string) {
  return provider.trim().toLowerCase();
}

function normalizeToPhone(phone: string) {
  return phone.replace(/\D/g, "");
}

function randomMockMessageId() {
  if (typeof crypto !== "undefined" && "randomUUID" in crypto && typeof crypto.randomUUID === "function") {
    return `mock-${crypto.randomUUID()}`;
  }

  return `mock-${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`;
}

function isMockAllowed() {
  const explicit = process.env.WHATSAPP_ALLOW_SIMULATED_SEND?.trim().toLowerCase();
  if (process.env.NODE_ENV === "production") {
    return false;
  }

  if (explicit === undefined) {
    return true;
  }

  return explicit === "true" || explicit === "1" || explicit === "yes";
}

async function sendViaMeta({
  to,
  content,
  phoneNumberId
}: {
  to: string;
  content: string;
  phoneNumberId: string;
}) {
  const token = process.env.WHATSAPP_API_TOKEN?.trim();
  const version = process.env.WHATSAPP_API_VERSION?.trim() || "v22.0";

  if (!token) {
    return {
      success: false,
      failureReason: "WHATSAPP_API_TOKEN is not configured"
    };
  }

  const normalizedTo = normalizeToPhone(to);
  const response = await fetch(`https://graph.facebook.com/${version}/${phoneNumberId}/messages`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      messaging_product: "whatsapp",
      to: normalizedTo,
      type: "text",
      text: {
        preview_url: false,
        body: content
      }
    })
  });

  const payloadText = await response.text();
  let parsed: MetaResponse = {};
  try {
    parsed = JSON.parse(payloadText) as MetaResponse;
  } catch {
    // ignore parse error
  }

  if (!response.ok) {
    return {
      success: false,
      failureReason: parsed.error?.message
        ? `Meta API error: ${parsed.error.message}`
        : `Meta API ${response.status}: ${payloadText.slice(0, 400)}`
    };
  }

  const providerMessageId = parsed.messages?.[0]?.id?.trim();
  if (!providerMessageId) {
    return {
      success: false,
      failureReason: "Meta API success response does not include message id"
    };
  }

  return {
    success: true,
    providerMessageId
  };
}

export async function sendOutboundTextMessage(input: OutboundMessageRequest): Promise<OutboundMessageResult> {
  const normalized = normalizeProvider(input.channelProvider);
  const defaultResult: OutboundMessageResult = {
    success: false,
    provider: normalized || "unknown",
    deliveryStatus: DeliveryStatus.FAILED
  };

  if (!input.phoneNumberId || !input.to || !input.content) {
    return {
      ...defaultResult,
      failureReason: "Missing recipient or message data"
    };
  }

  if (!normalized.includes("meta")) {
    if (isMockAllowed()) {
      return {
        success: true,
        provider: "mock",
        deliveryStatus: DeliveryStatus.SENT,
        providerMessageId: randomMockMessageId()
      };
    }

    return {
      ...defaultResult,
      failureReason: `Unsupported provider "${input.channelProvider}". Configure WhatsApp provider or enable simulation.`
    };
  }

  const metaResult = await sendViaMeta({
    to: input.to,
    content: input.content,
    phoneNumberId: input.phoneNumberId
  });

  if (!metaResult.success) {
    if (!isMockAllowed()) {
      return {
        ...defaultResult,
        provider: "meta",
        failureReason: metaResult.failureReason
      };
    }

    return {
      success: true,
      provider: "mock",
      deliveryStatus: DeliveryStatus.SENT,
      providerMessageId: randomMockMessageId(),
      failureReason: metaResult.failureReason
    };
  }

  return {
    success: true,
    provider: "meta",
    deliveryStatus: DeliveryStatus.SENT,
    providerMessageId: metaResult.providerMessageId
  };
}
