<?php

namespace App\Helpers;

use App\Models\MalaysiaPostcode;

class PoslajuValidator
{
    /**
     * Sanitize text for Pos Laju API (remove special characters that might break JSON or API)
     *
     * @param string $text
     * @return string
     */
    public static function sanitizeText($text)
    {
        if (empty($text)) {
            return '';
        }

        // Convert to string if not already
        $text = (string) $text;

        // Remove control characters (newlines, tabs, etc.) but keep regular spaces
        $text = preg_replace('/[\x00-\x1F\x7F]/u', '', $text);

        // Replace problematic characters that might break JSON or APIs
        $replacements = [
            '`' => "'",          // Backtick to single quote
            '"' => "'",          // Double quote to single quote
            "\xE2\x80\x9C" => "'",  // Smart double quote (left) UTF-8
            "\xE2\x80\x9D" => "'",  // Smart double quote (right) UTF-8
            "\xE2\x80\x98" => "'",  // Smart single quote (left) UTF-8
            "\xE2\x80\x99" => "'",  // Smart single quote (right) UTF-8
            '\\' => '/',         // Backslash to forward slash
            "\r" => ' ',         // Carriage return to space
            "\n" => ' ',         // Newline to space
            "\t" => ' ',         // Tab to space
        ];

        $text = str_replace(array_keys($replacements), array_values($replacements), $text);

        // Remove multiple consecutive spaces
        $text = preg_replace('/\s+/', ' ', $text);

        // Trim and return
        return trim($text);
    }

    /**
     * Validate order data for Pos Laju AWB generation
     *
     * @param object $order
     * @return array ['valid' => bool, 'errors' => array, 'corrected' => array]
     */
    public static function validateOrder($order)
    {
        $errors = [];
        $corrected = [];
        $shipping = $order->shipping ?? $order->billing;
        $billing = $order->billing;

        // 1. Validate Phone Number
        $phone = $shipping['phone'] ?? $billing['phone'] ?? null;
        if (empty($phone)) {
            $errors[] = 'Phone number is required';
        } else {
            $formattedPhone = PhoneHelper::formatMalaysian($phone);
            if (!$formattedPhone || !PhoneHelper::isValid($formattedPhone)) {
                $errors[] = 'Invalid phone number format. Must be Malaysian number (+60...)';
            } else {
                $corrected['phone'] = $formattedPhone;
            }
        }

        // 2. Validate Email
        $email = $billing['email'] ?? null;
        if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
            // Use fallback email
            $corrected['email'] = config('mail.from.address', 'noreply@' . parse_url(config('app.url'), PHP_URL_HOST));
            $errors[] = 'No valid email found - using fallback: ' . $corrected['email'];
        } else {
            $corrected['email'] = $email;
        }

        // 3. Validate Postcode and State
        $postcode = $shipping['postcode'] ?? $billing['postcode'] ?? null;
        $state = $shipping['state'] ?? $billing['state'] ?? null;

        if (empty($postcode)) {
            $errors[] = 'Postcode is required';
        } elseif (!preg_match('/^\d{5}$/', $postcode)) {
            $errors[] = 'Invalid postcode format. Must be 5 digits';
        } else {
            // Check if postcode exists in database
            $postcodeRecord = MalaysiaPostcode::where('postcode', $postcode)->first();

            if (!$postcodeRecord) {
                // Try to find by range
                $postcodeRecord = self::findPostcodeByRange($postcode);
            }

            if ($postcodeRecord) {
                $correctedState = $postcodeRecord->state;

                // Compare with provided state (allow state code as well)
                $normalizedProvidedState = strtolower(trim($state));
                $normalizedCorrectState = strtolower(trim($correctedState));
                $normalizedStateCode = strtolower(trim($postcodeRecord->state_code));

                $isMatch = $normalizedProvidedState === $normalizedCorrectState ||
                          $normalizedProvidedState === $normalizedStateCode;

                if ($state && !$isMatch) {
                    $errors[] = "State mismatch: Postcode {$postcode} belongs to {$correctedState}, but order state is {$state}";
                    $corrected['state'] = $correctedState;
                    $corrected['state_code'] = $postcodeRecord->state_code;
                } else {
                    $corrected['state'] = $correctedState;
                    $corrected['state_code'] = $postcodeRecord->state_code;
                }

                // Also set correct city if available
                if ($postcodeRecord->city) {
                    $corrected['city'] = $postcodeRecord->city;
                }
            } else {
                $errors[] = "Postcode {$postcode} not found in Malaysia postcode database";
            }
        }

        // 4. Validate Address (support both 'address_1' and 'address' formats)
        $address = $shipping['address_1'] ?? $shipping['address'] ?? $billing['address_1'] ?? $billing['address'] ?? null;
        if (empty($address)) {
            $errors[] = 'Address is required';
        } else {
            $corrected['address'] = self::sanitizeText($address);
        }

        // 5. Validate Name (support both 'first_name'+'last_name' and 'name' formats)
        // Check if there's a full 'name' field first (sales pages)
        $fullName = $shipping['name'] ?? $billing['name'] ?? null;

        // If not, construct from first_name + last_name (checkout/WooCommerce)
        if (empty($fullName)) {
            $firstName = $shipping['first_name'] ?? $billing['first_name'] ?? '';
            $lastName = $shipping['last_name'] ?? $billing['last_name'] ?? '';
            $fullName = trim($firstName . ' ' . $lastName);
        }

        if (empty($fullName)) {
            $errors[] = 'Customer name is required';
        } else {
            $corrected['name'] = self::sanitizeText($fullName);
        }

        // 6. Validate Country (must be MY or Malaysia)
        $country = $shipping['country'] ?? $billing['country'] ?? null;
        $normalizedCountry = strtoupper(trim($country ?? ''));

        // Accept both "MY" and "Malaysia"
        if ($country && $normalizedCountry !== 'MY' && $normalizedCountry !== 'MALAYSIA') {
            $errors[] = 'Pos Laju only supports Malaysian addresses (country must be MY or Malaysia)';
        } else {
            $corrected['country'] = 'MY';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
            'corrected' => $corrected
        ];
    }

    /**
     * Find postcode by range when exact match not found
     */
    protected static function findPostcodeByRange($postcode)
    {
        $postcodeInt = intval($postcode);

        // Find postcodes in similar range (first 2 digits match)
        $prefixPattern = substr($postcode, 0, 2) . '%';

        $nearest = MalaysiaPostcode::where('postcode', 'like', $prefixPattern)
            ->first();

        return $nearest;
    }

    /**
     * Get corrected shipping address for Pos Laju
     */
    public static function getCorrectedAddress($order)
    {
        $validation = self::validateOrder($order);

        if (!$validation['valid']) {
            return [
                'success' => false,
                'errors' => $validation['errors']
            ];
        }

        $shipping = $order->shipping ?? $order->billing;
        $billing = $order->billing;

        return [
            'success' => true,
            'data' => [
                'name' => $validation['corrected']['name'],
                'phone' => $validation['corrected']['phone'],
                'email' => $validation['corrected']['email'],
                'address_line_1' => $validation['corrected']['address'],
                'address_line_2' => $shipping['address_2'] ?? '',
                'postcode' => $shipping['postcode'] ?? $billing['postcode'],
                'city' => $validation['corrected']['city'] ?? $shipping['city'] ?? $billing['city'],
                'state' => $validation['corrected']['state'],
                'state_code' => $validation['corrected']['state_code'] ?? '',
                'country' => 'MY',
            ]
        ];
    }

    /**
     * Check if order is eligible for Pos Laju shipping
     */
    public static function isEligible($order)
    {
        $validation = self::validateOrder($order);
        return $validation['valid'];
    }

    /**
     * Get validation errors as formatted string
     */
    public static function getErrorMessage($order)
    {
        $validation = self::validateOrder($order);
        return implode('; ', $validation['errors']);
    }
}
