<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * DigiExpress status to message conversion engine.
 */
class DX_Status_Engine {

    public const STATUS_WARNING = 1;
    public const STATUS_ERROR   = 2;
    public const STATUS_INFO    = 3;
    public const STATUS_SUCCESS = 4;

    /**
     * Single source of truth for human-readable event titles (timeline, fallbacks, UI labels).
     * Aligns with resolve_message() titles where applicable. Event 3: registered / ready for pickup & send (not cancelled).
     *
     * @param int $event_id DigiExpress event_type.id
     * @return string Empty string if unknown.
     */
    public static function get_event_display_title( int $event_id ): string {
        $map = [
            0  => 'مرسوله ثبت نشده',
            1  => 'در حال ثبت',
            2  => 'ثبت شده با بازه بارگیری',
            3  => 'مرسوله ثبت شد؛ آماده بارگیری و ارسال',
            4  => 'خطای ثبت',
            5  => 'خطای ثبت',
            6  => 'خطای بارگیری',
            7  => 'خطای بارگیری',
            8  => 'لغو شده',
            9  => 'لغو شده',
            10 => 'در مسیر',
            11 => 'در مسیر',
            12 => 'در مسیر',
            13 => 'در مسیر',
            14 => 'در حال ارسال به مشتری',
            15 => 'در حال ارسال به مشتری',
            16 => 'در حال ارسال به مشتری',
            17 => 'در حال ارسال به مشتری',
            18 => 'تحویل شده',
            19 => 'تحویل شده',
            20 => 'تحویل ناموفق',
            21 => 'هماهنگی برای ارسال مجدد',
            22 => 'برگشت به فرستنده',
            23 => 'برگشت به فرستنده',
            24 => 'برگشت به فرستنده',
            25 => 'برگشت به فرستنده',
            26 => 'مرسوله برگشت داده شد',
            27 => 'مرسوله برگشت داده شد',
            28 => 'در مسیر',
            29 => 'در مسیر',
            30 => 'در مسیر',
        ];
        return $map[ $event_id ] ?? '';
    }

    /**
     * Resolve a message from DigiExpress event data.
     *
     * @param array $dx_data Webhook detail structure containing event_type.id and payload.
     * @return array|null [ 'title' => string|null, 'message' => string, 'status' => int ] or null for unknown event.
     */
    public static function resolve_message( $dx_data ) {
        if ( ! is_array( $dx_data ) ) {
            return null;
        }

        try {
            $event_id = isset( $dx_data['event_type']['id'] ) ? (int) $dx_data['event_type']['id'] : null;
            $payload  = isset( $dx_data['payload'] ) && is_array( $dx_data['payload'] ) ? $dx_data['payload'] : [];

            if ( $event_id === null ) {
                return null;
            }

            switch ( $event_id ) {
                case 0:
                    return [
                        'title'   => self::get_event_display_title( 0 ),
                        'message' => 'مرسوله ثبت نشده و تاریخ بارگیری ندارد.',
                        'status'  => self::STATUS_WARNING,
                    ];
                case 1:
                    return [
                        'title'   => self::get_event_display_title( 1 ),
                        'message' => 'ثبت مرسوله در حال انجام است.',
                        'status'  => self::STATUS_INFO,
                    ];
                case 2:
                    return self::build_pickup_date_message( $payload );
                case 3:
                    return null;
                case 4:
                case 5:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'ثبت مرسوله با خطا مواجه شده است.',
                        'status'  => self::STATUS_ERROR,
                    ];
                case 6:
                case 7:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'بارگیری مرسوله انجام نشد.',
                        'status'  => self::STATUS_ERROR,
                    ];
                case 8:
                case 9:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'مرسوله لغو شده است.',
                        'status'  => self::STATUS_WARNING,
                    ];
                case 10:
                case 11:
                case 12:
                case 13:
                case 28:
                case 29:
                case 30:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'مرسوله در حال انتقال است.',
                        'status'  => self::STATUS_INFO,
                    ];
                case 14:
                case 15:
                case 16:
                case 17:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'مرسوله در حال ارسال به آدرس مشتری است.',
                        'status'  => self::STATUS_INFO,
                    ];
                case 18:
                case 19:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'مرسوله به مشتری تحویل داده شده است.',
                        'status'  => self::STATUS_SUCCESS,
                    ];
                case 20:
                    return self::build_failure_reason_message( $dx_data, $payload );
                case 21:
                    return [
                        'title'   => self::get_event_display_title( 21 ),
                        'message' => 'مشتری در دریافت مرسوله حاضر نبود؛ هماهنگی برای ارسال مجدد انجام می‌شود.',
                        'status'  => self::STATUS_WARNING,
                    ];
                case 22:
                case 23:
                case 24:
                case 25:
                    return [
                        'title'   => self::get_event_display_title( $event_id ),
                        'message' => 'به دلیل عدم حضور مشتری، مرسوله برگشت داده شده است.',
                        'status'  => self::STATUS_WARNING,
                    ];
                default:
                    return null;
            }
        } catch ( \Throwable $e ) {
            if ( function_exists( 'error_log' ) ) {
                error_log( '[BWDK DX_Status_Engine] ' . $e->getMessage() );
            }
            return null;
        }
    }

    /**
     * Resolve a message from DigiExpress shipment_status (selected_shipping_data.shipment_status).
     *
     * This is used when event detail is missing/zero but shipment identifiers exist, so UI does not
     * incorrectly treat "no label" or status placeholders as "not registered in DigiExpress".
     *
     * @param string $shipment_status Raw shipment_status (e.g. UnregisteredShipment).
     * @param bool   $has_identifiers True when shipment_id or shipment_code exists.
     * @return array|null [ 'title' => string|null, 'message' => string, 'status' => int ] or null for unknown.
     */
    public static function resolve_shipment_status( string $shipment_status, bool $has_identifiers ): ?array {
        $raw = trim( $shipment_status );
        if ( $raw === '' ) {
            return null;
        }

        $key = strtolower( $raw );
        switch ( $key ) {
            case 'unregisteredshipment':
                if ( $has_identifiers ) {
                    return [
                        'title'   => 'ثبت شده / در انتظار تکمیل دیجی‌اکسپرس',
                        'message' => 'مرسوله در دیجی‌اکسپرس ایجاد شده است اما هنوز ثبت نهایی/بازه بارگیری تکمیل نشده است.',
                        'status'  => self::STATUS_INFO,
                    ];
                }
                return [
                    'title'   => 'مرسوله ثبت نشده',
                    'message' => 'هنوز ثبت مرسوله در دیجی‌اکسپرس انجام نشده است.',
                    'status'  => self::STATUS_WARNING,
                ];
            default:
                return null;
        }
    }

    protected static function build_pickup_date_message( array $payload ) {
        $start_raw = isset( $payload['pick_up_date_start'] ) ? trim( (string) $payload['pick_up_date_start'] ) : '';
        $end_raw   = isset( $payload['pick_up_date_end'] ) ? trim( (string) $payload['pick_up_date_end'] ) : '';

        $start_ts = strtotime( $start_raw );
        $end_ts   = strtotime( $end_raw );

        if ( $start_ts !== false && $end_ts !== false ) {
            $date_start = date( 'Y/m/d', $start_ts );
            $date_end   = date( 'Y/m/d', $end_ts );
            $h_start    = date( 'G', $start_ts );
            $h_end      = date( 'G', $end_ts );
            $time_range = sprintf( '%02d - %02d', $h_start, $h_end );

            if ( $date_start === $date_end ) {
                $message = sprintf( 'مرسوله ثبت شده است. تاریخ بارگیری: %s، بازه زمانی: %s', $date_start, $time_range );
            } else {
                $message = sprintf( 'مرسوله ثبت شده است. تاریخ بارگیری از %s تا %s، بازه زمانی: %s', $date_start, $date_end, $time_range );
            }

            return [
                'title'   => self::get_event_display_title( 2 ),
                'message' => $message,
                'status'  => self::STATUS_INFO,
            ];
        }

        return [
            'title'   => self::get_event_display_title( 1 ),
            'message' => 'ثبت مرسوله در حال انجام است.',
            'status'  => self::STATUS_INFO,
        ];
    }

    protected static function build_failure_reason_message( array $data, array $payload ) {
        $reason = '';

        if ( isset( $payload['failure_reason'] ) ) {
            $reason = trim( (string) $payload['failure_reason'] );
        }

        if ( $reason === '' && isset( $data['last_mile_failure_reason'] ) ) {
            $reason = trim( (string) $data['last_mile_failure_reason'] );
        }

        $map = [
            'CustomerAbsent' => [
                'title'   => 'تحویل ناموفق - عدم حضور مشتری',
                'message' => 'مرسوله در اولین تلاش تحویل داده نشد؛ مشتری حاضر نبود. هماهنگی برای ارسال مجدد.',
            ],
            'NoCoverage' => [
                'title'   => 'هماهنگی برای ارسال مجدد',
                'message' => 'به دلیل عدم پوشش، ارسال مجدد هماهنگ می‌شود.',
            ],
            'WrongAddress' => [
                'title'   => 'هماهنگی برای ارسال مجدد',
                'message' => 'آدرس نادرست بود؛ ارسال مجدد با آدرس صحیح هماهنگ می‌شود.',
            ],
            'CustomerRefused' => [
                'title'   => 'هماهنگی برای ارسال مجدد',
                'message' => 'مشتری از دریافت مرسوله خودداری کرد؛ هماهنگی برای ارسال مجدد.',
            ],
            'NoCode' => [
                'title'   => 'هماهنگی برای ارسال مجدد',
                'message' => 'کد تحویل در دسترس نبود؛ ارسال مجدد هماهنگ می‌شود.',
            ],
            'AddressNotFound' => [
                'title'   => 'آدرس نامشخص',
                'message' => 'آدرس وارد شده یافت نشد؛ اطلاعات آدرس باید تصحیح و ارسال مجدد شود.',
            ],
            'ReceiverNotAvailable' => [
                'title'   => 'عدم امکان تحویل - گیرنده در دسترس نیست',
                'message' => 'تحویل مرسوله ممکن نیست؛ هماهنگی برای ارسال مجدد انجام می‌شود.',
            ],
            'PackageDamaged' => [
                'title'   => 'آسیب بسته',
                'message' => 'بسته در فرایند تحویل آسیب دیده است؛ در حال بررسی برای تصمیم گیری بعدی.',
            ],
            'default' => [
                'title'   => 'هماهنگی برای ارسال مجدد',
                'message' => 'تحویل انجام نشد؛ هماهنگی برای ارسال مجدد انجام می‌شود.',
            ],
        ];

        $entry = $map[ $reason ] ?? $map['default'];

        return [
            'title'   => $entry['title'],
            'message' => $entry['message'],
            'status'  => self::STATUS_WARNING,
        ];
    }
}
