const API_URL =
  process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, '');

type SendOtpResponse = {
  expiresAt: string;
};

type VerifyOtpResponse = {
  success: boolean;
  message: string;
  verified: boolean;
};

function getErrorMessage(result: unknown, fallback: string): string {
  if (typeof result !== 'object' || result === null || !('message' in result)) {
    return fallback;
  }

  const { message } = result;

  if (typeof message === 'string' && message.trim()) {
    return message;
  }

  if (Array.isArray(message)) {
    const messages = message.filter(
      (item): item is string => typeof item === 'string' && item.trim().length > 0,
    );

    if (messages.length > 0) {
      return messages.join('. ');
    }
  }

  return fallback;
}

function isSendOtpResponse(value: unknown): value is SendOtpResponse {
  return (
    typeof value === 'object' &&
    value !== null &&
    'expiresAt' in value &&
    typeof value.expiresAt === 'string' &&
    Number.isFinite(Date.parse(value.expiresAt))
  );
}

function isVerifyOtpResponse(value: unknown): value is VerifyOtpResponse {
  return (
    typeof value === 'object' &&
    value !== null &&
    'success' in value &&
    typeof value.success === 'boolean' &&
    'message' in value &&
    typeof value.message === 'string' &&
    'verified' in value &&
    typeof value.verified === 'boolean'
  );
}

export async function sendOtp(mobile: string): Promise<SendOtpResponse> {
  const response = await fetch(
    `${API_URL}/api/v1/otp/send`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        mobile: mobile.trim(),
        purpose: 'registration',
      }),
    },
  );

  const result: unknown = await response.json().catch(() => null);

  if (!response.ok) {
    throw new Error(getErrorMessage(result, 'Failed to send OTP'));
  }

  if (!isSendOtpResponse(result)) {
    throw new Error('OTP response did not include a valid expiry time.');
  }

  return result;
}

export async function verifyOtp(
  mobile: string,
  otp: string,
) {
  const response = await fetch(
    `${API_URL}/api/v1/otp/verify`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        mobile: mobile.trim(),
        otp: otp.trim(),
        purpose: 'registration',
      }),
    },
  );

  const result: unknown = await response.json().catch(() => null);

  if (!response.ok) {
    throw new Error(getErrorMessage(result, 'Invalid OTP'));
  }

  if (!isVerifyOtpResponse(result)) {
    throw new Error('OTP verification response was invalid.');
  }

  return result;
}