<?php
/**
 * Address Validator.
 *
 * Validates and sanitizes billing/shipping address data
 * submitted during checkout.
 *
 * @package TitanCart\Modules\Checkout
 */

namespace TitanCart\Modules\Checkout;

defined( 'ABSPATH' ) || exit;

class AddressValidator {

    /**
     * Billing-required fields.
     * Extend via 'titancart_billing_required_fields' filter.
     */
    private const BILLING_REQUIRED = [
        'billing_first_name',
        'billing_last_name',
        'billing_email',
        'billing_phone',
        'billing_address_1',
        'billing_city',
        'billing_country',
        'billing_postcode',
    ];

    /**
     * Shipping-required fields (when ship_to_different_address = true).
     */
    private const SHIPPING_REQUIRED = [
        'shipping_first_name',
        'shipping_last_name',
        'shipping_address_1',
        'shipping_city',
        'shipping_country',
        'shipping_postcode',
    ];

    /**
     * Validate address data.
     *
     * @param  array $data                      Raw POST data.
     * @param  bool  $ship_to_different_address Whether a separate shipping address was provided.
     * @return array{ valid: bool, errors: array<string,string> }
     */
    public function validate( array $data, bool $ship_to_different_address ): array {
        $errors = [];

        $billing_required = apply_filters(
            'titancart_billing_required_fields',
            self::BILLING_REQUIRED
        );

        foreach ( $billing_required as $field ) {
            if ( empty( $data[ $field ] ) ) {
                $errors[ $field ] = sprintf(
                    /* translators: %s: field label */
                    __( '%s is required.', 'titancart-lite' ),
                    $this->field_label( $field )
                );
            }
        }

        // Email format check.
        if ( ! empty( $data['billing_email'] ) && ! is_email( $data['billing_email'] ) ) {
            $errors['billing_email'] = __( 'Please enter a valid email address.', 'titancart-lite' );
        }

        // Separate shipping address validation.
        if ( $ship_to_different_address ) {
            $shipping_required = apply_filters(
                'titancart_shipping_required_fields',
                self::SHIPPING_REQUIRED
            );

            foreach ( $shipping_required as $field ) {
                if ( empty( $data[ $field ] ) ) {
                    $errors[ $field ] = sprintf(
                        /* translators: %s: address field label (e.g. "City"). */
                        __( '%s is required.', 'titancart-lite' ),
                        $this->field_label( $field )
                    );
                }
            }
        }

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

    /**
     * Sanitize and extract address fields from raw input.
     * Returns two arrays: billing and shipping.
     *
     * When $ship_to_different_address is false, shipping mirrors billing.
     *
     * @param  array $data
     * @param  bool  $ship_to_different_address
     * @return array{ billing: array, shipping: array }
     */
    public function extract( array $data, bool $ship_to_different_address ): array {
        $billing = [
            'first_name' => sanitize_text_field( $data['billing_first_name'] ?? '' ),
            'last_name'  => sanitize_text_field( $data['billing_last_name']  ?? '' ),
            'company'    => sanitize_text_field( $data['billing_company']    ?? '' ),
            'email'      => sanitize_email( $data['billing_email']           ?? '' ),
            'phone'      => sanitize_text_field( $data['billing_phone']      ?? '' ),
            'address_1'  => sanitize_text_field( $data['billing_address_1']  ?? '' ),
            'address_2'  => sanitize_text_field( $data['billing_address_2']  ?? '' ),
            'city'       => sanitize_text_field( $data['billing_city']       ?? '' ),
            'state'      => sanitize_text_field( $data['billing_state']      ?? '' ),
            'postcode'   => sanitize_text_field( $data['billing_postcode']   ?? '' ),
            'country'    => sanitize_text_field( $data['billing_country']    ?? '' ),
        ];

        if ( $ship_to_different_address ) {
            $shipping = [
                'first_name' => sanitize_text_field( $data['shipping_first_name'] ?? '' ),
                'last_name'  => sanitize_text_field( $data['billing_last_name']   ?? '' ),
                'company'    => sanitize_text_field( $data['shipping_company']    ?? '' ),
                'address_1'  => sanitize_text_field( $data['shipping_address_1']  ?? '' ),
                'address_2'  => sanitize_text_field( $data['shipping_address_2']  ?? '' ),
                'city'       => sanitize_text_field( $data['shipping_city']       ?? '' ),
                'state'      => sanitize_text_field( $data['shipping_state']      ?? '' ),
                'postcode'   => sanitize_text_field( $data['shipping_postcode']   ?? '' ),
                'country'    => sanitize_text_field( $data['shipping_country']    ?? '' ),
            ];
        } else {
            // Shipping mirrors billing (minus email/phone — not needed for shipping).
            $shipping = array_diff_key( $billing, array_flip( [ 'email', 'phone' ] ) );
        }

        return compact( 'billing', 'shipping' );
    }

    /**
     * Human-readable label for a field key.
     *
     * @param  string $field  e.g. 'billing_first_name'
     * @return string
     */
    private function field_label( string $field ): string {
        $labels = [
            'billing_first_name' => __( 'First name', 'titancart-lite' ),
            'billing_last_name'  => __( 'Last name',  'titancart-lite' ),
            'billing_email'      => __( 'Email',      'titancart-lite' ),
            'billing_phone'      => __( 'Phone',      'titancart-lite' ),
            'billing_address_1'  => __( 'Address',    'titancart-lite' ),
            'billing_city'       => __( 'City',       'titancart-lite' ),
            'billing_country'    => __( 'Country',    'titancart-lite' ),
            'billing_postcode'   => __( 'Postcode / ZIP', 'titancart-lite' ),
            'billing_state'      => __( 'State / Province', 'titancart-lite' ),
            'shipping_first_name' => __( 'Shipping first name', 'titancart-lite' ),
            'shipping_last_name'  => __( 'Shipping last name',  'titancart-lite' ),
            'shipping_address_1'  => __( 'Shipping address',    'titancart-lite' ),
            'shipping_city'       => __( 'Shipping city',       'titancart-lite' ),
            'shipping_country'    => __( 'Shipping country',    'titancart-lite' ),
            'shipping_postcode'   => __( 'Shipping postcode',   'titancart-lite' ),
        ];

        return $labels[ $field ] ?? ucwords( str_replace( [ 'billing_', 'shipping_', '_' ], [ '', '', ' ' ], $field ) );
    }
}
