import DatabaseProperty from "./Database/DatabaseProperty";
import BadDataException from "./Exception/BadDataException";
import { ObjectType } from "./JSON";
import Zod from "../Utils/Schema/Zod";
class Phone extends DatabaseProperty {
    get phone() {
        return this._phone;
    }
    static pickPhoneNumberToSendSMSOrCallFrom(data) {
        /*
         * convert all to string, so that we can compare them
         * if the country code matches in secondary phone numbers, then pick that number
         * if no country code matches, then pick the primary phone number and return it.
         */
        const to = typeof data.to === "string" ? data.to : data.to.toString();
        const primaryPhoneNumberToPickFrom = typeof data.primaryPhoneNumberToPickFrom === "string"
            ? data.primaryPhoneNumberToPickFrom
            : data.primaryPhoneNumberToPickFrom.toString();
        const secondaryPhoneNumbersToPickFrom = data.secondaryPhoneNumbersToPickFrom.map((phone) => {
            return typeof phone === "string" ? phone : phone.toString();
        });
        const normalizePhoneNumber = (phone) => {
            phone = phone.trim();
            return phone.startsWith("+") ? phone.substring(1) : phone;
        };
        const toCountryCode = normalizePhoneNumber(to).substring(0, 2);
        const primaryPhoneNumberToPickFromCountryCode = normalizePhoneNumber(primaryPhoneNumberToPickFrom).substring(0, 2);
        if (toCountryCode === primaryPhoneNumberToPickFromCountryCode) {
            return new Phone(primaryPhoneNumberToPickFrom);
        }
        for (const secondaryPhoneNumber of secondaryPhoneNumbersToPickFrom) {
            const secondaryPhoneNumberCountryCode = normalizePhoneNumber(secondaryPhoneNumber).substring(0, 2);
            if (toCountryCode === secondaryPhoneNumberCountryCode) {
                return new Phone(secondaryPhoneNumber);
            }
        }
        return new Phone(primaryPhoneNumberToPickFrom);
    }
    set phone(v) {
        /*
         * TODO: Have a valid regex for phone.
         * const re: RegExp =
         *     /^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+.)+[^<>()[\].,;:\s@"]{2,})$/i;
         * const isValid: boolean = re.test(v);
         * if (!isValid) {
         *     throw new BadDataException('Phone is not in valid format.');
         * }
         */
        v = v.trim();
        const re = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,7}$/; // regex for international phone numbers format based on (ITU-T E.123)
        const isValid = re.test(v);
        if (!isValid) {
            throw new BadDataException(`Phone is not in valid format: ${v}`);
        }
        this._phone = v;
    }
    constructor(phone) {
        super();
        this._phone = "";
        if (phone instanceof Phone) {
            phone = phone.phone;
        }
        this.phone = phone;
    }
    toString() {
        return this.phone;
    }
    toJSON() {
        return {
            _type: ObjectType.Phone,
            value: this.toString(),
        };
    }
    static fromJSON(json) {
        if (json["_type"] === ObjectType.Phone) {
            return new Phone(json["value"] || "");
        }
        throw new BadDataException("Invalid JSON: " + JSON.stringify(json));
    }
    static toDatabase(value) {
        if (value) {
            if (typeof value === "string") {
                value = new Phone(value);
            }
            return value.toString();
        }
        return null;
    }
    static fromDatabase(_value) {
        if (_value) {
            return new Phone(_value);
        }
        return null;
    }
    static getSchema() {
        return Zod.object({
            _type: Zod.literal(ObjectType.Phone),
            value: Zod.string().openapi({
                type: "string",
                example: "+1-555-123-4567",
            }),
        }).openapi({
            type: "object",
            description: "Phone object",
            example: { _type: ObjectType.Phone, value: "+1-555-123-4567" },
        });
    }
    /**
     * Extract ISO country code from a phone number
     * @param phoneNumber - The phone number (e.g., "+15551234567")
     * @returns ISO country code (e.g., "US") or "US" as default
     */
    static getCountryCodeFromPhoneNumber(phoneNumber) {
        for (const [prefix, countryCode] of Object.entries(Phone.CALLING_CODE_TO_COUNTRY_MAP)) {
            if (phoneNumber.startsWith(prefix)) {
                return countryCode;
            }
        }
        return "US"; // Default to US if unknown
    }
    /**
     * Extract area code from a phone number
     * Currently only supports US/Canada (+1) numbers
     * @param phoneNumber - The phone number (e.g., "+15551234567")
     * @returns Area code (e.g., "555") or empty string for non-US/CA numbers
     */
    static getAreaCodeFromPhoneNumber(phoneNumber) {
        // For US/Canada numbers (+1), extract the next 3 digits
        if (phoneNumber.startsWith("+1")) {
            const number = phoneNumber.substring(2);
            if (number.length >= 3) {
                return number.substring(0, 3);
            }
        }
        // For other countries, area code extraction is more complex
        return "";
    }
}
// Map of calling code prefixes to ISO country codes
Phone.CALLING_CODE_TO_COUNTRY_MAP = {
    "+1": "US", // US and Canada
    "+44": "GB", // United Kingdom
    "+61": "AU", // Australia
    "+49": "DE", // Germany
    "+33": "FR", // France
    "+91": "IN", // India
    "+81": "JP", // Japan
    "+86": "CN", // China
    "+55": "BR", // Brazil
    "+52": "MX", // Mexico
};
export default Phone;
//# sourceMappingURL=Phone.js.map