/**
 * SMS/OTP provider abstraction. Production uses Twilio; local dev logs OTP to console.
 */

export interface OtpSendRequest {
  phone: string;
  code: string;
  countryCode?: string;
  locale?: string;
  expiresMinutes?: number;
}

export interface OtpSendResult {
  success: boolean;
  messageId?: string;
  provider: string;
  /** Dev-only: echoed OTP when using DevSmsProvider */
  devCode?: string;
  error?: string;
}

export interface SmsProvider {
  readonly name: string;
  sendOtp(request: OtpSendRequest): Promise<OtpSendResult>;
}

export class DevSmsProvider implements SmsProvider {
  readonly name = "dev";

  async sendOtp(request: OtpSendRequest): Promise<OtpSendResult> {
    console.log(
      `[DevSmsProvider] OTP for ${request.phone}: ${request.code} (expires in ${request.expiresMinutes ?? 5}m)`,
    );
    return {
      success: true,
      provider: this.name,
      messageId: `dev_${Date.now()}`,
      devCode: request.code,
    };
  }
}

/**
 * Twilio stub — wire TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER in production.
 * Throws until credentials are configured; keeps dev path on DevSmsProvider.
 */
export class TwilioSmsProvider implements SmsProvider {
  readonly name = "twilio";

  constructor(
    private readonly accountSid = process.env.TWILIO_ACCOUNT_SID,
    private readonly authToken = process.env.TWILIO_AUTH_TOKEN,
    private readonly fromNumber = process.env.TWILIO_FROM_NUMBER,
  ) {}

  async sendOtp(request: OtpSendRequest): Promise<OtpSendResult> {
    if (!this.accountSid || !this.authToken || !this.fromNumber) {
      return {
        success: false,
        provider: this.name,
        error: "Twilio credentials not configured (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER)",
      };
    }

    const body = `AGNET verification code: ${request.code}. Valid for ${request.expiresMinutes ?? 5} minutes.`;
    const url = `https://api.twilio.com/2010-04-01/Accounts/${this.accountSid}/Messages.json`;
    const auth = Buffer.from(`${this.accountSid}:${this.authToken}`).toString("base64");

    const params = new URLSearchParams({
      To: request.phone,
      From: this.fromNumber,
      Body: body,
    });

    const response = await fetch(url, {
      method: "POST",
      headers: {
        Authorization: `Basic ${auth}`,
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: params.toString(),
    });

    if (!response.ok) {
      const detail = await response.text().catch(() => response.statusText);
      return { success: false, provider: this.name, error: detail };
    }

    const data = (await response.json()) as { sid?: string };
    return { success: true, provider: this.name, messageId: data.sid };
  }
}

export function createSmsProvider(): SmsProvider {
  if (process.env.NODE_ENV === "production" && process.env.SMS_PROVIDER === "twilio") {
    return new TwilioSmsProvider();
  }
  return new DevSmsProvider();
}

let defaultProvider: SmsProvider | undefined;

export function getSmsProvider(): SmsProvider {
  if (!defaultProvider) {
    defaultProvider = createSmsProvider();
  }
  return defaultProvider;
}

export function setSmsProvider(provider: SmsProvider): void {
  defaultProvider = provider;
}
