<?php

namespace App\Support;

/**
 * WhatsApp deep-link helpers. "Sending" a document over WhatsApp is a
 * wa.me link with a pre-filled message: the phone number (international
 * format, digits only) plus a URL-encoded message body. The browser/app
 * then opens the chat with the draft text ready to hit send.
 */
final class WhatsApp
{
    /**
     * Normalize a phone number to the digits-only international format
     * wa.me expects. Local Sri Lankan formats are converted to the +94
     * prefix ("077 123 4567" → "94771234567"); anything that already looks
     * international ("+94…", "94…", "44…") passes through as its digits.
     */
    public static function e164Digits(string $phone): string
    {
        $digits = preg_replace('/\D+/', '', $phone) ?? '';

        if (strlen($digits) === 10 && str_starts_with($digits, '0')) {
            return '94'.substr($digits, 1);
        }

        if (strlen($digits) === 9 && str_starts_with($digits, '7')) {
            return '94'.$digits;
        }

        return $digits;
    }

    public static function link(string $phone, string $message): string
    {
        return 'https://wa.me/'.self::e164Digits($phone).'?text='.rawurlencode($message);
    }

    /**
     * Is this a group invite link (`https://chat.whatsapp.com/…`)?
     *
     * Worth its own predicate because the two destination shapes behave
     * differently and the difference is not negotiable: a wa.me link to a
     * number accepts `?text=`, so the message arrives pre-filled; a group
     * invite accepts no message parameter whatsoever. WhatsApp exposes no way
     * to pre-fill a group message from a link, so callers targeting a group
     * have to put the text somewhere the sender can paste it from.
     */
    public static function isGroupInvite(string $target): bool
    {
        return preg_match('#^https?://chat\.whatsapp\.com/#i', trim($target)) === 1;
    }

    /**
     * Turn a configured destination into the URL to open.
     *
     * Accepts what a person would reasonably paste into a "WhatsApp link"
     * field: a bare phone number, a wa.me link, or a group invite link.
     * Returns null for anything that is not one of those, so a typo shows up
     * as a hidden button rather than a broken tab.
     *
     * The message is attached only where WhatsApp can carry it — see
     * {@see isGroupInvite()}.
     */
    public static function linkForTarget(string $target, string $message): ?string
    {
        $target = trim($target);

        if ($target === '') {
            return null;
        }

        if (self::isGroupInvite($target)) {
            // No ?text= — the invite link ignores it. The caller hands the
            // sender the message another way.
            return $target;
        }

        // A wa.me / api.whatsapp.com link the landlord pasted: keep their host
        // and path, replace whatever query it came with so the message is ours.
        if (preg_match('#^https?://(?:api\.whatsapp\.com/send|wa\.me)/?#i', $target) === 1) {
            $parts = parse_url($target);

            if ($parts === false || ! isset($parts['host'])) {
                return null;
            }

            $path = rtrim($parts['path'] ?? '', '/');

            // api.whatsapp.com carries the number in ?phone=, wa.me in the path.
            parse_str($parts['query'] ?? '', $query);
            $phone = self::e164Digits((string) ($query['phone'] ?? basename($path)));

            if ($phone === '') {
                return null;
            }

            return 'https://wa.me/'.$phone.'?text='.rawurlencode($message);
        }

        $digits = self::e164Digits($target);

        // A plausible international number is at least a country code and a
        // subscriber number; anything shorter is a typo, not a destination.
        return strlen($digits) >= 8
            ? 'https://wa.me/'.$digits.'?text='.rawurlencode($message)
            : null;
    }
}
