<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Tests\Unit;

use OCA\Mitgliederverwaltung\Validation\PhoneValidator;
use PHPUnit\Framework\TestCase;

/**
 * Comprehensive unit tests for PhoneValidator.
 *
 * Covers E.164 validation, normalization from German and international formats,
 * and error message quality per Issue #66.
 */
class PhoneValidatorTest extends TestCase {

    // ── Valid E.164 numbers ─────────────────────────────────────────

    public function testValidGermanMobile(): void {
        $this->assertTrue(PhoneValidator::isValid('+4917612345678'));
    }

    public function testValidGermanLandline(): void {
        $this->assertTrue(PhoneValidator::isValid('+493012345678'));
    }

    public function testValidInternationalUS(): void {
        $this->assertTrue(PhoneValidator::isValid('+12025551234'));
    }

    public function testValidInternationalUK(): void {
        $this->assertTrue(PhoneValidator::isValid('+442071234567'));
    }

    public function testValidAustrian(): void {
        $this->assertTrue(PhoneValidator::isValid('+4312345678'));
    }

    public function testValidSwiss(): void {
        $this->assertTrue(PhoneValidator::isValid('+41441234567'));
    }

    // ── Normalization: German local format ──────────────────────────

    public function testNormalizeGermanLocalToE164(): void {
        $result = PhoneValidator::validateAndNormalize('017612345678');
        $this->assertSame('+4917612345678', $result);
    }

    public function testNormalizeGermanLocalWithLeadingZero(): void {
        $result = PhoneValidator::validateAndNormalize('030 12345678');
        $this->assertSame('+493012345678', $result);
    }

    public function testNormalizeGermanLocalWithDashes(): void {
        $result = PhoneValidator::validateAndNormalize('0176-123-456-78');
        $this->assertSame('+4917612345678', $result);
    }

    public function testNormalizeGermanLocalWithParentheses(): void {
        $result = PhoneValidator::validateAndNormalize('(0176) 12345678');
        $this->assertSame('+4917612345678', $result);
    }

    public function testNormalizeGermanLocalWithSlash(): void {
        $result = PhoneValidator::validateAndNormalize('0176/12345678');
        $this->assertSame('+4917612345678', $result);
    }

    // ── Normalization: 00 prefix ────────────────────────────────────

    public function testNormalize00PrefixToPlus(): void {
        $result = PhoneValidator::validateAndNormalize('004917612345678');
        $this->assertSame('+4917612345678', $result);
    }

    // ── Already E.164 ───────────────────────────────────────────────

    public function testAlreadyE164PassesThrough(): void {
        $result = PhoneValidator::validateAndNormalize('+4917612345678');
        $this->assertSame('+4917612345678', $result);
    }

    // ── Invalid formats ─────────────────────────────────────────────

    public function testInvalidTooShortReturnsNull(): void {
        $this->assertNull(PhoneValidator::validateAndNormalize('+1'));
    }

    public function testInvalidTooLongReturnsNull(): void {
        // E.164 max is 15 digits after +
        $this->assertNull(PhoneValidator::validateAndNormalize('+1234567890123456'));
    }

    public function testInvalidLettersReturnsNull(): void {
        $this->assertNull(PhoneValidator::validateAndNormalize('+49abc1234'));
    }

    public function testEmptyStringReturnsNull(): void {
        $this->assertNull(PhoneValidator::validateAndNormalize(''));
    }

    // ── Error messages ──────────────────────────────────────────────

    public function testEmptyErrorMessage(): void {
        $msg = PhoneValidator::getErrorMessage('');
        $this->assertStringContainsString('leer', $msg);
    }

    public function testTooShortErrorMessage(): void {
        $msg = PhoneValidator::getErrorMessage('+1');
        $this->assertStringContainsString('kurz', $msg);
    }

    public function testTooLongErrorMessage(): void {
        $msg = PhoneValidator::getErrorMessage('+1234567890123456');
        $this->assertStringContainsString('lang', $msg);
    }

    public function testInvalidFormatErrorMessage(): void {
        $msg = PhoneValidator::getErrorMessage('abc');
        $this->assertNotEmpty($msg);
    }

    // ── Edge cases ──────────────────────────────────────────────────

    public function testWhitespaceOnlyReturnsNull(): void {
        $this->assertNull(PhoneValidator::validateAndNormalize('   '));
    }

    public function testNormalizationPreservesValidNumber(): void {
        $normalized = PhoneValidator::normalize('+4917612345678');
        $this->assertSame('+4917612345678', $normalized);
        $this->assertTrue(PhoneValidator::isValid($normalized));
    }
}
