import twilio from "twilio";
import { logger } from "@/lib/logger";

// Lazy-init Twilio client (only when first SMS is sent)
let twilioClient: twilio.Twilio | null = null;

function getClient(): twilio.Twilio {
  if (!twilioClient) {
    const accountSid = process.env.TWILIO_ACCOUNT_SID;
    const authToken = process.env.TWILIO_AUTH_TOKEN;

    if (!accountSid || !authToken) {
      throw new Error("Twilio credentials not configured");
    }

    twilioClient = twilio(accountSid, authToken);
  }
  return twilioClient;
}

/**
 * Normalize Australian phone numbers to E.164 format
 * Handles: 0412345678, +61412345678, 61412345678, 04 1234 5678
 */
export function normalizeAuPhone(phone: string): string | null {
  // Strip all non-digit characters except leading +
  const cleaned = phone.replace(/[^\d+]/g, "");

  // Already E.164 Australian
  if (/^\+614\d{8}$/.test(cleaned)) return cleaned;

  // Missing + prefix
  if (/^614\d{8}$/.test(cleaned)) return `+${cleaned}`;

  // Local format: 04XXXXXXXX
  if (/^04\d{8}$/.test(cleaned)) return `+61${cleaned.slice(1)}`;

  // Not a valid AU mobile
  return null;
}

/**
 * Validate that a phone number is a valid Australian mobile
 */
export function isValidAuMobile(phone: string): boolean {
  return normalizeAuPhone(phone) !== null;
}

export type SmsResult = {
  success: boolean;
  sid?: string;
  error?: string;
};

/**
 * Send an SMS via Twilio
 * 
 * Uses Messaging Service SID if available (better deliverability),
 * falls back to direct phone number.
 */
export async function sendSms(to: string, body: string): Promise<SmsResult> {
  const normalized = normalizeAuPhone(to);
  if (!normalized) {
    logger.warn(`SMS skipped: invalid phone number "${to}"`);
    return { success: false, error: `Invalid AU mobile: ${to}` };
  }

  // Truncate body to SMS-safe length (3 segments max = 480 chars)
  const truncatedBody = body.length > 480 ? body.slice(0, 477) + "..." : body;

  try {
    const client = getClient();
    const messagingServiceSid = process.env.TWILIO_MESSAGING_SERVICE_SID;
    const fromNumber = process.env.TWILIO_PHONE_NUMBER;

    const messageParams: { to: string; body: string; messagingServiceSid?: string; from?: string } = {
      to: normalized,
      body: truncatedBody,
    };

    if (messagingServiceSid) {
      messageParams.messagingServiceSid = messagingServiceSid;
    } else if (fromNumber) {
      messageParams.from = fromNumber;
    } else {
      throw new Error("No Twilio sender configured (need TWILIO_MESSAGING_SERVICE_SID or TWILIO_PHONE_NUMBER)");
    }

    const message = await client.messages.create(messageParams);

    logger.info(`SMS sent to ${normalized}: SID=${message.sid}`);
    return { success: true, sid: message.sid };
  } catch (error) {
    const errMsg = error instanceof Error ? error.message : "Unknown SMS error";
    logger.error(`SMS failed to ${normalized}: ${errMsg}`);
    return { success: false, error: errMsg };
  }
}

/**
 * SMS notification templates for RateRight events
 */
export const SMS_TEMPLATES = {
  workerApplied: (jobTitle: string, workerName: string) =>
    `RateRight: ${workerName} has applied for your "${jobTitle}" job. Open the app to review. rateright.com.au`,

  workerHired: (jobTitle: string, contractorName: string) =>
    `RateRight: Great news! ${contractorName} has hired you for "${jobTitle}". Open the app for details. rateright.com.au`,

  workerConfirmedStart: (jobTitle: string, workerName: string, startDate: string) =>
    `RateRight: ${workerName} confirmed start for "${jobTitle}" on ${startDate}. rateright.com.au`,

  noShowDetected: (jobTitle: string, workerName: string) =>
    `RateRight: ${workerName} did not show up for "${jobTitle}". We've flagged this. Contact support if needed. rateright.com.au`,

  noShowWarning: (jobTitle: string) =>
    `RateRight: You were marked as no-show for "${jobTitle}". This affects your profile rating. Contact support if this is wrong. rateright.com.au`,

  contractorHireConfirmed: (jobTitle: string, workerName: string, workerPhone: string) =>
    `RateRight: You hired ${workerName} for "${jobTitle}". Their number: ${workerPhone}. Manage in app. rateright.com.au`,

  hireReceipt: (jobTitle: string, amount: string) =>
    `RateRight: Payment of ${amount} confirmed for "${jobTitle}". Receipt in your dashboard. rateright.com.au`,
} as const;
