import { Injectable } from "@angular/core";

@Injectable({ providedIn: 'root' })
export class Validation {

    constructor(){ }

    validatePhoneNumber(input: string): [boolean, string] {
        var sanitized = input.replace(/\D/g, '');
        if (sanitized.length < 10){
            let formatted = sanitized.replace(/(\d{3})(?=\d{3})/g, '$1-').replace(/(\d{4})(?=\d{1,4}$)/, '$1-');
            return [false, formatted];
        } else if (sanitized.length === 10) {
            let result = `(${sanitized.slice(0, 3)})${sanitized.slice(3, 6)}-${sanitized.slice(6, 10)}`;
            return [true, result];
        } else if (sanitized.length > 10 && sanitized.length < 14) {
            let countryCode = sanitized.slice(0, sanitized.length - 10);
            let areaCode = sanitized.slice(sanitized.length - 10, sanitized.length - 7);
            let firstPart = sanitized.slice(sanitized.length - 7, sanitized.length - 4);
            let secondPart = sanitized.slice(sanitized.length - 4);
            let result = `+${countryCode} (${areaCode})${firstPart}-${secondPart}`;
            return [true, result];
        }else{
            return [false, input];
        }
    }

    emailRegex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    validateEmail(input: string): [boolean, string] {
        const trimmed = input.trim();
        const [local, domain] = trimmed.split('@');
        const corrected = domain ? `${local}@${domain.toLowerCase()}` : trimmed;

        // Extra checks to avoid invalid formats
        if ( corrected.includes('..') || corrected.startsWith('.') || corrected.endsWith('.') ) {
            return [false, corrected];
        }

        const success = this.emailRegex.test(corrected);
        return [success, corrected];
    }

    validateURL(input: string): [boolean, string] {
        const testUrl = /^https?:\/\//i.test(input) ? input : "http://" + input;
        var urlToParse = new URL(testUrl);
        try {

            if (urlToParse.protocol !== 'http:' && urlToParse.protocol !== 'https:') {
                return [false, "bad protocol"];
            }

            const hostname = urlToParse.hostname.toLowerCase();
            if (hostname === 'localhost' || hostname.endsWith('.localhost')) {
                return [false, "localhost not allowed"];
            }

            const privateIpRegex = /^(127\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/;
            if (privateIpRegex.test(hostname)) {
                return [false, "internal ipv4 not allowed"];
            }

            if (hostname.includes(':')) {
                if (this.isPrivateIPv6(hostname)) {
                    return [false, "internal ipv6 not allowed"];
                }
            }

            return [true, urlToParse.href.substring(0, urlToParse.href.length - 1)];
        } catch (e) {
            return [false, "validation error has occurred"];
        }
    }

    ///////// HELPER FUNCTIONS /////////

    isPrivateIPv6(ip: string): boolean {
        try {
            const normalized = ip.replace(/^\[|\]$/g, '').toLowerCase();
            if (normalized === '::1') return true;
            if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;
            const first4 = normalized.slice(0, 4);
            if (first4 >= 'fe80' && first4 <= 'febf') return true;
            return false;
        } catch {
            return true;
        }
    }

    ///////// GETTERS /////////

    get ValidCountries(): string[] {
        return ['AD', 'AE', 'AI', 'AL', 'AR', 'AS', 'AT', 'AU', 'AX', 'AZ', 'BD', 'BE', 'BG', 
                'BM', 'BR', 'BY', 'CA', 'CC', 'CH', 'CL', 'CN', 'CO', 'CR', 'CX', 'CY', 'CZ', 
                'DE', 'DK', 'DO', 'DZ', 'EC', 'EE', 'ES', 'FI', 'FK', 'FM', 'FO', 'FR', 'GB', 
                'GF', 'GG', 'GI', 'GL', 'GP', 'GS', 'GT', 'GU', 'HK', 'HM', 'HN', 'HR', 'HT', 
                'HU', 'ID', 'IE', 'IM', 'IN', 'IO', 'IS', 'IT', 'JE', 'JP', 'KE', 'KR', 'LI', 
                'LK', 'LT', 'LU', 'LV', 'MA', 'MC', 'MD', 'MH', 'MK', 'MO', 'MP', 'MQ', 'MT', 
                'MW', 'MX', 'MY', 'NC', 'NF', 'NL', 'NO', 'NR', 'NU', 'NZ', 'PA', 'PE', 'PF', 
                'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PT', 'PW', 'RE', 'RO', 'RS', 'RU', 'SE', 
                'SG', 'SI', 'SJ', 'SK', 'SM', 'TC', 'TH', 'TR', 'UA', 'US', 'UY', 'VA', 'VI', 
                'WF', 'WS', 'YT', 'ZA'];
    }

}