<?php
/**
 * Date Helper using Carbon.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Helpers;

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

/**
 * Date helper class using Carbon for robust date parsing.
 */
final class DateHelper {

    /**
     * Parse date string to Carbon instance or timestamp.
     *
     * @param string $date_string Date string in various formats.
     * @param string $format      Optional format hint.
     * @param bool   $return_timestamp Whether to return timestamp instead of Carbon instance.
     * @return \Carbon\Carbon|int|false Carbon instance, timestamp, or false on failure.
     */
    public static function parse( $date_string, $format = null, $return_timestamp = false ) {
        if ( empty( $date_string ) ) {
            return false;
        }

        // Try prefixed Carbon first (production), then normal Carbon (development)
        $carbon_class = null;
        if ( class_exists( '\PrimeLink\Vendor\Carbon\Carbon' ) ) {
            $carbon_class = '\PrimeLink\Vendor\Carbon\Carbon';
        } elseif ( class_exists( '\Carbon\Carbon' ) ) {
            $carbon_class = '\Carbon\Carbon';
        }

        if ( $carbon_class ) {
            try {
                // If already a timestamp
                if ( is_numeric( $date_string ) && strlen( $date_string ) >= 10 ) {
                    $carbon = $carbon_class::createFromTimestamp( absint( $date_string ) );
                    return $return_timestamp ? $carbon->timestamp : $carbon;
                }

                // Try with format if provided
                if ( ! empty( $format ) ) {
                    $carbon = $carbon_class::createFromFormat( $format, $date_string );
                    if ( $carbon ) {
                        return $return_timestamp ? $carbon->timestamp : $carbon;
                    }
                }

                // Try Carbon's intelligent parsing
                $carbon = $carbon_class::parse( $date_string );
                if ( $carbon ) {
                    return $return_timestamp ? $carbon->timestamp : $carbon;
                }
            } catch ( \Exception $e ) {
                // Fallback to native PHP
            }
        }

        // Fallback to native PHP DateTime
        return self::parse_native( $date_string, $format, $return_timestamp );
    }

    /**
     * Parse date using native PHP (fallback when Carbon is not available).
     *
     * @param string $date_string Date string.
     * @param string $format      Optional format hint.
     * @param bool   $return_timestamp Whether to return timestamp.
     * @return \DateTime|int|false
     */
    private static function parse_native( $date_string, $format = null, $return_timestamp = false ) {
        // If already a timestamp
        if ( is_numeric( $date_string ) && strlen( $date_string ) >= 10 ) {
            $timestamp = absint( $date_string );
            if ( $return_timestamp ) {
                return $timestamp;
            }
            $date = new \DateTime();
            $date->setTimestamp( $timestamp );
            return $date;
        }

        // Try with format if provided
        if ( ! empty( $format ) ) {
            $date = \DateTime::createFromFormat( $format, $date_string );
            if ( $date ) {
                return $return_timestamp ? $date->getTimestamp() : $date;
            }
        }

        // Try common formats
        $common_formats = array(
            'Y-m-d H:i:s',
            'Y-m-d H:i',
            'Y-m-d',
            'd/m/Y H:i:s',
            'd/m/Y H:i',
            'd/m/Y',
            'd-m-Y H:i:s',
            'd-m-Y H:i',
            'd-m-Y',
            'm/d/Y H:i:s',
            'm/d/Y H:i',
            'm/d/Y',
        );

        foreach ( $common_formats as $fmt ) {
            $date = \DateTime::createFromFormat( $fmt, $date_string );
            if ( $date ) {
                return $return_timestamp ? $date->getTimestamp() : $date;
            }
        }

        // Last resort: strtotime
        $timestamp = strtotime( $date_string );
        if ( $timestamp !== false ) {
            if ( $return_timestamp ) {
                return $timestamp;
            }
            $date = new \DateTime();
            $date->setTimestamp( $timestamp );
            return $date;
        }

        return false;
    }

    /**
     * Format date to string.
     *
     * @param \Carbon\Carbon|\DateTime|int|string $date   Date object, timestamp, or string.
     * @param string                               $format Format string.
     * @return string
     */
    public static function format( $date, $format ) {
        if ( empty( $date ) || empty( $format ) ) {
            return '';
        }

        // Carbon 2.x requires PHP 8.1+
        // If PHP < 8.1, use native fallback directly
        if ( version_compare( PHP_VERSION, '8.1.0', '<' ) ) {
            // Fallback to native PHP
            if ( $date instanceof \DateTime ) {
                return $date->format( $format );
            }
            if ( is_numeric( $date ) ) {
                $dt = new \DateTime();
                $dt->setTimestamp( $date );
                return $dt->format( $format );
            }
            return '';
        }

        // Try prefixed Carbon first (production), then normal Carbon (development)
        $carbon_class = null;
        if ( class_exists( '\PrimeLink\Vendor\Carbon\Carbon' ) ) {
            $carbon_class = '\PrimeLink\Vendor\Carbon\Carbon';
        } elseif ( class_exists( '\Carbon\Carbon' ) ) {
            $carbon_class = '\Carbon\Carbon';
        }

        if ( $carbon_class ) {
            try {
                // Check if date is already a Carbon instance (handle both prefixed and normal)
                if ( $date instanceof \Carbon\Carbon || $date instanceof \PrimeLink\Vendor\Carbon\Carbon ) {
                    return $date->format( $format );
                }
                if ( is_numeric( $date ) ) {
                    return $carbon_class::createFromTimestamp( $date )->format( $format );
                }
                if ( is_string( $date ) ) {
                    return $carbon_class::parse( $date )->format( $format );
                }
            } catch ( \Exception $e ) {
                // Fallback
            }
        }

        // Fallback to native PHP
        if ( $date instanceof \DateTime ) {
            return $date->format( $format );
        }
        if ( is_numeric( $date ) ) {
            $dt = new \DateTime();
            $dt->setTimestamp( $date );
            return $dt->format( $format );
        }

        return '';
    }

    /**
     * Parse date to timestamp (convenience method).
     *
     * @param string $date_string Date string.
     * @param string $format      Optional format hint.
     * @return int|false Timestamp or false on failure.
     */
    public static function parse_to_timestamp( $date_string, $format = null ) {
        $result = self::parse( $date_string, $format, true );
        return $result !== false ? (int) $result : false;
    }
}

