import { Buffer } from 'buffer';

export type CommunicationProvider = 'INTERNAL_PANEL' | 'RESEND' | 'TWILIO' | 'WHATSAPP_CLOUD';
export type CommunicationDeliveryMode = 'REAL' | 'SIMULATED' | 'PARTIAL';
export type CommunicationChannelKey = 'inApp' | 'email' | 'sms' | 'whatsapp';

export type CommunicationProviderStatus = {
  channel: 'IN_APP' | 'EMAIL' | 'SMS' | 'WHATSAPP';
  provider: CommunicationProvider;
  enabled: boolean;
  configured: boolean;
  mode: 'REAL' | 'SIMULATED';
  supportedRecipients: string;
  summary: string;
  missingEnv: string[];
};

type ChannelPreferences = Record<CommunicationChannelKey, boolean>;

export type DeliveryAttemptInput = {
  channel: 'EMAIL' | 'SMS' | 'WHATSAPP';
  destination: string | null;
  title: string;
  message: string;
  eventType: string;
  appointmentId: string;
  startsAt: string;
  motivo: string;
  status: string;
  recipientName: string;
  recipientRole: 'PATIENT' | 'DENTIST';
  dentistName: string;
  reason?: string | null;
};

export type DeliveryAttemptResult = {
  status: 'SENT' | 'SIMULATED' | 'SKIPPED' | 'FAILED';
  provider: CommunicationProvider;
  providerMessageId: string | null;
  detail: string | null;
  errorMessage: string | null;
};

const resolveEnv = (key: string) => {
  const rawValue = process.env[key];
  return typeof rawValue === 'string' && rawValue.trim() ? rawValue.trim() : null;
};

const formatPhoneNumber = (value: string | null) => {
  if (!value) {
    return null;
  }

  const trimmedValue = value.trim();

  if (!trimmedValue) {
    return null;
  }

  const digits = trimmedValue.replace(/\D/g, '');

  if (!digits) {
    return null;
  }

  if (trimmedValue.startsWith('+')) {
    return `+${digits}`;
  }

  const defaultCountryCode = resolveEnv('COMMUNICATION_DEFAULT_COUNTRY_CODE');

  if (defaultCountryCode) {
    const normalizedCountryCode = defaultCountryCode.replace(/\D/g, '');
    return `+${normalizedCountryCode}${digits}`;
  }

  return digits;
};

const formatDateTime = (value: string) =>
  new Intl.DateTimeFormat('es-PE', {
    timeZone: 'America/Lima',
    day: '2-digit',
    month: 'short',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  }).format(new Date(value));

const escapeHtml = (value: string) =>
  value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');

const getWhatsappActionLabel = (input: Pick<DeliveryAttemptInput, 'eventType' | 'status'>) => {
  switch (input.eventType) {
    case 'APPOINTMENT_CREATED':
      return 'agendada';
    case 'APPOINTMENT_RESCHEDULED':
      return 'reprogramada';
    case 'APPOINTMENT_STATUS_CHANGED':
      return `actualizada al estado ${input.status.toLowerCase()}`;
    default:
      return 'actualizada';
  }
};

const buildEmailHtml = (input: DeliveryAttemptInput) => {
  const reasonBlock = input.reason
    ? `<p style="margin:0;color:#475569;font-size:14px;"><strong>Motivo adicional:</strong> ${escapeHtml(input.reason)}</p>`
    : '';

  return `
    <div style="background:#f8fafc;padding:24px;font-family:Arial,sans-serif;color:#0f172a;">
      <div style="max-width:640px;margin:0 auto;background:#ffffff;border-radius:24px;padding:32px;border:1px solid #e2e8f0;">
        <p style="margin:0 0 8px;font-size:12px;letter-spacing:0.18em;text-transform:uppercase;color:#64748b;">DentaFlow</p>
        <h1 style="margin:0 0 16px;font-size:28px;line-height:1.2;color:#0c4a6e;">${escapeHtml(input.title)}</h1>
        <p style="margin:0 0 20px;font-size:15px;line-height:1.7;color:#334155;">${escapeHtml(input.message)}</p>
        <div style="border-radius:18px;background:#f8fafc;padding:18px 20px;margin-bottom:20px;">
          <p style="margin:0 0 10px;color:#0f172a;font-size:14px;"><strong>Paciente:</strong> ${escapeHtml(input.recipientRole === 'PATIENT' ? input.recipientName : 'Paciente asignado')}</p>
          <p style="margin:0 0 10px;color:#0f172a;font-size:14px;"><strong>Fecha:</strong> ${escapeHtml(formatDateTime(input.startsAt))}</p>
          <p style="margin:0 0 10px;color:#0f172a;font-size:14px;"><strong>Motivo:</strong> ${escapeHtml(input.motivo)}</p>
          <p style="margin:0;color:#0f172a;font-size:14px;"><strong>Odontologo:</strong> ${escapeHtml(input.dentistName)}</p>
        </div>
        ${reasonBlock}
        <p style="margin:20px 0 0;color:#64748b;font-size:13px;">Este mensaje fue generado automaticamente por el sistema de agenda.</p>
      </div>
    </div>
  `;
};

const parseJsonResponse = async <T>(response: Response) => {
  const responseText = await response.text();

  if (!responseText) {
    return null;
  }

  try {
    return JSON.parse(responseText) as T;
  } catch {
    return null;
  }
};

const buildProviderStatus = (
  channel: CommunicationProviderStatus['channel'],
  provider: CommunicationProvider,
  enabled: boolean,
  supportedRecipients: string,
  summary: string,
  requiredEnv: string[],
): CommunicationProviderStatus => {
  const missingEnv = requiredEnv.filter((envKey) => !resolveEnv(envKey));

  return {
    channel,
    provider,
    enabled,
    configured: missingEnv.length === 0,
    mode: missingEnv.length === 0 ? 'REAL' : 'SIMULATED',
    supportedRecipients,
    summary,
    missingEnv,
  };
};

export const buildCommunicationProviderStatuses = (channels: ChannelPreferences) => {
  const providerStatus = {
    inApp: {
      channel: 'IN_APP',
      provider: 'INTERNAL_PANEL',
      enabled: channels.inApp,
      configured: true,
      mode: 'REAL',
      supportedRecipients: 'Doctor y panel administrativo',
      summary: 'Visible en la campana del sistema y en el centro de notificaciones interno.',
      missingEnv: [],
    } satisfies CommunicationProviderStatus,
    email: buildProviderStatus(
      'EMAIL',
      'RESEND',
      channels.email,
      'Paciente y doctor',
      'Envia correos automaticos por Resend cuando existen `RESEND_API_KEY` y `EMAIL_FROM`.',
      ['RESEND_API_KEY', 'EMAIL_FROM'],
    ),
    sms: buildProviderStatus(
      'SMS',
      'TWILIO',
      channels.sms,
      'Paciente',
      'Envia SMS por Twilio. Conviene registrar telefonos en formato E.164 o definir `COMMUNICATION_DEFAULT_COUNTRY_CODE`.',
      ['TWILIO_ACCOUNT_SID', 'TWILIO_AUTH_TOKEN', 'TWILIO_SMS_FROM_NUMBER'],
    ),
    whatsapp: buildProviderStatus(
      'WHATSAPP',
      'WHATSAPP_CLOUD',
      channels.whatsapp,
      'Paciente',
      'Envia WhatsApp por Cloud API con plantilla aprobada de 5 variables: nombre, accion, fecha, motivo y odontologo.',
      ['WHATSAPP_ACCESS_TOKEN', 'WHATSAPP_PHONE_NUMBER_ID', 'WHATSAPP_TEMPLATE_NAME', 'WHATSAPP_TEMPLATE_LANGUAGE'],
    ),
  };

  const enabledExternalStatuses = [providerStatus.email, providerStatus.sms, providerStatus.whatsapp].filter(
    (status) => status.enabled,
  );
  const readyExternalStatuses = enabledExternalStatuses.filter((status) => status.mode === 'REAL');

  const externalDeliveryMode: CommunicationDeliveryMode =
    enabledExternalStatuses.length === 0
      ? 'SIMULATED'
      : readyExternalStatuses.length === enabledExternalStatuses.length
        ? 'REAL'
        : readyExternalStatuses.length > 0
          ? 'PARTIAL'
          : 'SIMULATED';

  return {
    providerStatus,
    externalDeliveryMode,
  };
};

const sendEmail = async (input: DeliveryAttemptInput): Promise<DeliveryAttemptResult> => {
  const apiKey = resolveEnv('RESEND_API_KEY');
  const from = resolveEnv('EMAIL_FROM');

  if (!apiKey || !from) {
    return {
      status: 'SIMULATED',
      provider: 'RESEND',
      providerMessageId: null,
      detail: 'Correo registrado en modo simulado por falta de credenciales de Resend.',
      errorMessage: null,
    };
  }

  try {
    const response = await fetch('https://api.resend.com/emails', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        from,
        to: [input.destination],
        subject: input.title,
        text: input.message,
        html: buildEmailHtml(input),
        ...(resolveEnv('EMAIL_REPLY_TO') ? { reply_to: resolveEnv('EMAIL_REPLY_TO') } : {}),
      }),
    });

    const payload = await parseJsonResponse<{ id?: string; message?: string; error?: { message?: string } }>(response);

    if (!response.ok) {
      return {
        status: 'FAILED',
        provider: 'RESEND',
        providerMessageId: null,
        detail: null,
        errorMessage: payload?.error?.message ?? payload?.message ?? `Resend respondio con ${response.status}.`,
      };
    }

    return {
      status: 'SENT',
      provider: 'RESEND',
      providerMessageId: payload?.id ?? null,
      detail: 'Correo enviado correctamente por Resend.',
      errorMessage: null,
    };
  } catch (error) {
    return {
      status: 'FAILED',
      provider: 'RESEND',
      providerMessageId: null,
      detail: null,
      errorMessage: error instanceof Error ? error.message : 'No se pudo conectar con Resend.',
    };
  }
};

const sendSms = async (input: DeliveryAttemptInput): Promise<DeliveryAttemptResult> => {
  const accountSid = resolveEnv('TWILIO_ACCOUNT_SID');
  const authToken = resolveEnv('TWILIO_AUTH_TOKEN');
  const fromNumber = resolveEnv('TWILIO_SMS_FROM_NUMBER');
  const destination = formatPhoneNumber(input.destination);

  if (!accountSid || !authToken || !fromNumber) {
    return {
      status: 'SIMULATED',
      provider: 'TWILIO',
      providerMessageId: null,
      detail: 'SMS registrado en modo simulado por falta de credenciales de Twilio.',
      errorMessage: null,
    };
  }

  if (!destination) {
    return {
      status: 'SKIPPED',
      provider: 'TWILIO',
      providerMessageId: null,
      detail: 'No hay telefono valido para enviar el SMS.',
      errorMessage: null,
    };
  }

  try {
    const body = new URLSearchParams({
      From: fromNumber,
      To: destination,
      Body: input.message,
    });

    const response = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`, {
      method: 'POST',
      headers: {
        Authorization: `Basic ${Buffer.from(`${accountSid}:${authToken}`).toString('base64')}`,
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body,
    });

    const payload = await parseJsonResponse<{ sid?: string; message?: string }>(response);

    if (!response.ok) {
      return {
        status: 'FAILED',
        provider: 'TWILIO',
        providerMessageId: null,
        detail: null,
        errorMessage: payload?.message ?? `Twilio respondio con ${response.status}.`,
      };
    }

    return {
      status: 'SENT',
      provider: 'TWILIO',
      providerMessageId: payload?.sid ?? null,
      detail: 'SMS enviado correctamente por Twilio.',
      errorMessage: null,
    };
  } catch (error) {
    return {
      status: 'FAILED',
      provider: 'TWILIO',
      providerMessageId: null,
      detail: null,
      errorMessage: error instanceof Error ? error.message : 'No se pudo conectar con Twilio.',
    };
  }
};

const sendWhatsapp = async (input: DeliveryAttemptInput): Promise<DeliveryAttemptResult> => {
  const accessToken = resolveEnv('WHATSAPP_ACCESS_TOKEN');
  const phoneNumberId = resolveEnv('WHATSAPP_PHONE_NUMBER_ID');
  const templateName = resolveEnv('WHATSAPP_TEMPLATE_NAME');
  const templateLanguage = resolveEnv('WHATSAPP_TEMPLATE_LANGUAGE');
  const destination = formatPhoneNumber(input.destination);

  if (!accessToken || !phoneNumberId || !templateName || !templateLanguage) {
    return {
      status: 'SIMULATED',
      provider: 'WHATSAPP_CLOUD',
      providerMessageId: null,
      detail: 'WhatsApp registrado en modo simulado por falta de credenciales o plantilla aprobada.',
      errorMessage: null,
    };
  }

  if (!destination) {
    return {
      status: 'SKIPPED',
      provider: 'WHATSAPP_CLOUD',
      providerMessageId: null,
      detail: 'No hay telefono valido para enviar el WhatsApp.',
      errorMessage: null,
    };
  }

  const apiVersion = resolveEnv('WHATSAPP_API_VERSION') ?? 'v25.0';

  try {
    const response = await fetch(`https://graph.facebook.com/${apiVersion}/${phoneNumberId}/messages`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${accessToken}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        messaging_product: 'whatsapp',
        recipient_type: 'individual',
        to: destination,
        type: 'template',
        template: {
          name: templateName,
          language: {
            code: templateLanguage,
          },
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', text: input.recipientName },
                { type: 'text', text: getWhatsappActionLabel(input) },
                { type: 'text', text: formatDateTime(input.startsAt) },
                { type: 'text', text: input.motivo },
                { type: 'text', text: input.dentistName },
              ],
            },
          ],
        },
      }),
    });

    const payload = await parseJsonResponse<{
      messages?: Array<{ id?: string }>;
      error?: { message?: string };
    }>(response);

    if (!response.ok) {
      return {
        status: 'FAILED',
        provider: 'WHATSAPP_CLOUD',
        providerMessageId: null,
        detail: null,
        errorMessage: payload?.error?.message ?? `WhatsApp Cloud API respondio con ${response.status}.`,
      };
    }

    return {
      status: 'SENT',
      provider: 'WHATSAPP_CLOUD',
      providerMessageId: payload?.messages?.[0]?.id ?? null,
      detail: 'WhatsApp enviado correctamente por Cloud API.',
      errorMessage: null,
    };
  } catch (error) {
    return {
      status: 'FAILED',
      provider: 'WHATSAPP_CLOUD',
      providerMessageId: null,
      detail: null,
      errorMessage: error instanceof Error ? error.message : 'No se pudo conectar con WhatsApp Cloud API.',
    };
  }
};

export const deliverExternalCommunication = async (input: DeliveryAttemptInput) => {
  if (!input.destination) {
    return {
      status: 'SKIPPED',
      provider: input.channel === 'EMAIL' ? 'RESEND' : input.channel === 'SMS' ? 'TWILIO' : 'WHATSAPP_CLOUD',
      providerMessageId: null,
      detail: 'No existe un destino configurado para este canal.',
      errorMessage: null,
    } satisfies DeliveryAttemptResult;
  }

  if (input.channel === 'EMAIL') {
    return sendEmail(input);
  }

  if (input.channel === 'SMS') {
    return sendSms(input);
  }

  return sendWhatsapp(input);
};
