<?php

namespace App\Helpers;

use Carbon\Carbon;
use Morilog\Jalali\Jalalian;
use Hekmatinasser\Verta\Verta;

class DateHelper
{
    /**
     * Format date based on current locale
     *
     * @param mixed $date
     * @param string $format
     * @param string|null $locale
     * @return string
     */
    public static function formatByLocale($date, $format = 'Y/m/d', $locale = null)
    {
        if (!$date) {
            return '';
        }

        // Get current locale if not provided
        if (!$locale) {
            $locale = app()->getLocale();
        }

        // Convert to Carbon instance if needed
        if (!$date instanceof Carbon) {
            $date = Carbon::parse($date);
        }

        // Return Persian date for Persian locale
        if ($locale === 'fa') {
            return self::toPersian($date, $format);
        }

        // Return Gregorian date for other locales
        return self::toGregorian($date, $format);
    }

    /**
     * Format date with time based on current locale
     *
     * @param mixed $date
     * @param string|null $locale
     * @return string
     */
    public static function formatDateTimeByLocale($date, $locale = null)
    {
        if (!$date) {
            return '';
        }

        // Get current locale if not provided
        if (!$locale) {
            $locale = app()->getLocale();
        }

        // Convert to Carbon instance if needed
        if (!$date instanceof Carbon) {
            $date = Carbon::parse($date);
        }

        // Return Persian date for Persian locale
        if ($locale === 'fa') {
            return self::toPersian($date, 'Y/m/d H:i');
        }

        // Return Gregorian date for other locales
        return self::toGregorian($date, 'Y-m-d H:i');
    }

    /**
     * Format date for display based on current locale
     *
     * @param mixed $date
     * @param string|null $locale
     * @return string
     */
    public static function formatForDisplay($date, $locale = null)
    {
        if (!$date) {
            return '';
        }

        // Get current locale if not provided
        if (!$locale) {
            $locale = app()->getLocale();
        }

        // Convert to Carbon instance if needed
        if (!$date instanceof Carbon) {
            $date = Carbon::parse($date);
        }

        // Return Persian date for Persian locale
        if ($locale === 'fa') {
            return self::toPersian($date, 'l j F Y');
        }

        // Return Gregorian date for other locales
        return $date->format('l, F j, Y');
    }

    /**
     * Format relative time based on current locale
     *
     * @param mixed $date
     * @param string|null $locale
     * @return string
     */
    public static function formatRelativeByLocale($date, $locale = null)
    {
        if (!$date) {
            return '';
        }

        // Get current locale if not provided
        if (!$locale) {
            $locale = app()->getLocale();
        }

        // Convert to Carbon instance if needed
        if (!$date instanceof Carbon) {
            $date = Carbon::parse($date);
        }

        // Return Persian relative time for Persian locale
        if ($locale === 'fa') {
            return self::toPersianRelative($date);
        }

        // Return English relative time for other locales
        return $date->diffForHumans();
    }

    /**
     * Convert date to Persian (Jalali)
     *
     * @param Carbon $date
     * @param string $format
     * @return string
     */
    public static function toPersian(Carbon $date, $format = 'Y/m/d')
    {
        try {
            // Use Morilog Jalali package
            return Jalalian::fromDateTime($date)->format($format);
        } catch (\Exception $e) {
            // Fallback to Verta package
            try {
                return Verta::instance($date)->format($format);
            } catch (\Exception $e2) {
                // Final fallback to Gregorian
                return $date->format($format);
            }
        }
    }

    /**
     * Convert date to Gregorian
     *
     * @param Carbon $date
     * @param string $format
     * @return string
     */
    public static function toGregorian(Carbon $date, $format = 'Y-m-d')
    {
        return $date->format($format);
    }

    /**
     * Convert to Persian relative time
     *
     * @param Carbon $date
     * @return string
     */
    public static function toPersianRelative(Carbon $date)
    {
        $now = Carbon::now();
        $diffInSeconds = $now->diffInSeconds($date);
        $diffInMinutes = $now->diffInMinutes($date);
        $diffInHours = $now->diffInHours($date);
        $diffInDays = $now->diffInDays($date);
        $diffInWeeks = $now->diffInWeeks($date);
        $diffInMonths = $now->diffInMonths($date);
        $diffInYears = $now->diffInYears($date);

        $isPast = $date->isPast();
        $suffix = $isPast ? 'پیش' : 'دیگر';

        if ($diffInSeconds < 60) {
            return 'همین الان';
        } elseif ($diffInMinutes < 60) {
            return self::convertToPersianNumbers($diffInMinutes) . ' دقیقه ' . $suffix;
        } elseif ($diffInHours < 24) {
            return self::convertToPersianNumbers($diffInHours) . ' ساعت ' . $suffix;
        } elseif ($diffInDays < 7) {
            return self::convertToPersianNumbers($diffInDays) . ' روز ' . $suffix;
        } elseif ($diffInWeeks < 4) {
            return self::convertToPersianNumbers($diffInWeeks) . ' هفته ' . $suffix;
        } elseif ($diffInMonths < 12) {
            return self::convertToPersianNumbers($diffInMonths) . ' ماه ' . $suffix;
        } else {
            return self::convertToPersianNumbers($diffInYears) . ' سال ' . $suffix;
        }
    }

    /**
     * Convert numbers to Persian
     *
     * @param mixed $input
     * @return string
     */
    public static function convertToPersianNumbers($input)
    {
        $englishNumbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
        $persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];

        return str_replace($englishNumbers, $persianNumbers, $input);
    }

    /**
     * Convert numbers to English
     *
     * @param mixed $input
     * @return string
     */
    public static function convertToEnglishNumbers($input)
    {
        $persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
        $englishNumbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

        return str_replace($persianNumbers, $englishNumbers, $input);
    }

    /**
     * Get month name in Persian
     *
     * @param int $month
     * @return string
     */
    public static function getPersianMonthName($month)
    {
        $months = [
            1 => 'فروردین',
            2 => 'اردیبهشت',
            3 => 'خرداد',
            4 => 'تیر',
            5 => 'مرداد',
            6 => 'شهریور',
            7 => 'مهر',
            8 => 'آبان',
            9 => 'آذر',
            10 => 'دی',
            11 => 'بهمن',
            12 => 'اسفند'
        ];

        return $months[$month] ?? '';
    }

    /**
     * Get day name in Persian
     *
     * @param int $day (0 = Saturday, 1 = Sunday, etc.)
     * @return string
     */
    public static function getPersianDayName($day)
    {
        $days = [
            0 => 'شنبه',
            1 => 'یکشنبه',
            2 => 'دوشنبه',
            3 => 'سه‌شنبه',
            4 => 'چهارشنبه',
            5 => 'پنج‌شنبه',
            6 => 'جمعه'
        ];

        return $days[$day] ?? '';
    }

    /**
     * Format date for specific contexts
     *
     * @param mixed $date
     * @param string $context
     * @param string|null $locale
     * @return string
     */
    public static function formatForContext($date, $context = 'default', $locale = null)
    {
        if (!$date) {
            return '';
        }

        // Get current locale if not provided
        if (!$locale) {
            $locale = app()->getLocale();
        }

        // Convert to Carbon instance if needed
        if (!$date instanceof Carbon) {
            $date = Carbon::parse($date);
        }

        switch ($context) {
            case 'short':
                return $locale === 'fa' ? self::toPersian($date, 'Y/m/d') : $date->format('Y-m-d');
            
            case 'medium':
                return $locale === 'fa' ? self::toPersian($date, 'j F Y') : $date->format('M j, Y');
            
            case 'long':
                return $locale === 'fa' ? self::toPersian($date, 'l j F Y') : $date->format('l, F j, Y');
            
            case 'time':
                return $date->format('H:i');
            
            case 'datetime':
                return $locale === 'fa' ? self::toPersian($date, 'Y/m/d H:i') : $date->format('Y-m-d H:i');
            
            case 'relative':
                return self::formatRelativeByLocale($date, $locale);
            
            default:
                return self::formatByLocale($date, 'Y/m/d', $locale);
        }
    }
}
