import type { Customer } from '../billing/middleware.js';
import type { WhatsAppCredentials } from '../multitenancy/credential-store.js';
import { createToolAudit } from '../multitenancy/audit-log.js';

const WHATSAPP_API_VERSION = 'v18.0';
const WHATSAPP_BASE_URL = process.env['WHATSAPP_API_BASE_URL'] ?? 'https://graph.facebook.com';

function getEnvVar(account: string, key: string): string {
  const envKey = `WHATSAPP_${account.toUpperCase()}_${key}`;
  return process.env[envKey] ?? '';
}

function getPhoneNumberId(account: string): string {
  return getEnvVar(account, 'PHONE_NUMBER_ID');
}

function getAccessToken(account: string): string {
  return getEnvVar(account, 'ACCESS_TOKEN');
}

function getBusinessAccountId(account: string): string {
  return getEnvVar(account, 'BUSINESS_ACCOUNT_ID');
}

interface WhatsAppMessageResponse {
  messaging_product: string;
  contacts?: Array<{ wa_id: string; input: string }>;
  messages?: Array<{ id: string }>;
}

async function whatsappApiRequest(
  phoneId: string,
  accessToken: string,
  endpoint: string,
  method: 'GET' | 'POST' = 'POST',
  body?: unknown
) {
  const url = `${WHATSAPP_BASE_URL}/${WHATSAPP_API_VERSION}/${phoneId}/${endpoint}`;
  const res = await fetch(url, {
    method,
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: body ? JSON.stringify(body) : undefined,
    signal: AbortSignal.timeout(10000),
  });

  if (!res.ok) {
    const error = await res.text();
    throw new Error(`WhatsApp API error (${res.status}): ${error}`);
  }

  return res.json();
}

async function resolveWhatsAppCreds(
  args: { account?: string },
  customer?: Customer
): Promise<{ phoneId: string; accessToken: string; businessAccountId: string }> {
  if (customer) {
    const creds = await customer.getCredential<WhatsAppCredentials>('whatsapp');
    if (!creds) throw new Error('WhatsApp not connected for this account');
    return {
      phoneId: creds.phoneNumberId,
      accessToken: creds.accessToken,
      businessAccountId: creds.businessAccountId,
    };
  }
  const account = args.account ?? 'default';
  const phoneId = getPhoneNumberId(account);
  const accessToken = getAccessToken(account);
  const businessAccountId = getBusinessAccountId(account);
  if (!phoneId || !accessToken) {
    throw new Error('Missing WhatsApp credentials. Set WHATSAPP_{ACCOUNT}_PHONE_NUMBER_ID and WHATSAPP_{ACCOUNT}_ACCESS_TOKEN');
  }
  return { phoneId, accessToken, businessAccountId };
}

export async function sendMessage(
  args: { to: string; message: string; account?: string },
  customer?: Customer
): Promise<{ success: boolean; message_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'whatsapp:sendMessage') : null;
  const auditArgs = { to: args.to };

  const { phoneId, accessToken } = await resolveWhatsAppCreds(args, customer);

  const body = {
    messaging_product: 'whatsapp',
    to: args.to,
    type: 'text',
    text: { body: args.message },
  };

  try {
    const data = await whatsappApiRequest(phoneId, accessToken, 'messages', 'POST', body);
    const response = data as WhatsAppMessageResponse;
    const result = { success: true, message_id: response.messages?.[0]?.id ?? '' };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}

export async function sendTemplate(
  args: { to: string; template_name: string; language?: string; components?: unknown[]; account?: string },
  customer?: Customer
): Promise<{ success: boolean; message_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'whatsapp:sendTemplate') : null;
  const auditArgs = { to: args.to, template_name: args.template_name };

  const { phoneId, accessToken } = await resolveWhatsAppCreds(args, customer);

  const body: Record<string, unknown> = {
    messaging_product: 'whatsapp',
    to: args.to,
    type: 'template',
    template: {
      name: args.template_name,
      language: { code: args.language ?? 'en' },
    },
  };

  if (args.components) {
    (body.template as Record<string, unknown>).components = args.components;
  }

  try {
    const data = await whatsappApiRequest(phoneId, accessToken, 'messages', 'POST', body);
    const response = data as WhatsAppMessageResponse;
    const result = { success: true, message_id: response.messages?.[0]?.id ?? '' };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}

export async function getMessageStatus(
  args: { message_id: string; account?: string },
  _customer?: Customer
): Promise<{ message_id: string; status: string; timestamp?: string }> {
  // Meta Cloud API doesn't support polling message status via GET
  // Status updates are only available via webhooks (push-based)
  throw new Error('whatsapp_get_message_status is not supported. Meta Cloud API only provides delivery status via webhooks. Use POST /api/whatsapp/webhook to receive status updates.');
}

export async function listTemplates(
  args: { account?: string },
  customer?: Customer
): Promise<{ templates: Array<{ name: string; language: string; status: string }> }> {
  const { businessAccountId, accessToken } = await resolveWhatsAppCreds(args, customer);

  if (!businessAccountId) {
    throw new Error('Missing WhatsApp credentials. Set WHATSAPP_{ACCOUNT}_BUSINESS_ACCOUNT_ID');
  }

  const url = `${WHATSAPP_BASE_URL}/${WHATSAPP_API_VERSION}/${businessAccountId}/message_templates?fields=name,language,status`;
  const res = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
    signal: AbortSignal.timeout(10000),
  });

  if (!res.ok) {
    const error = await res.text();
    throw new Error(`WhatsApp API error (${res.status}): ${error}`);
  }

  const data = await res.json();
  return {
    templates: (data.data ?? []).map((t: { name: string; language: string | { code: string }; status: string }) => ({
      name: t.name,
      language: typeof t.language === 'string' ? t.language : t.language?.code ?? 'en',
      status: t.status,
    })),
  };
}
