<?php

namespace App\Helpers;

class DateHelper
{
    /**
     * Convert Gregorian date to Persian (Jalali) date
     * 
     * @param int|null $year Gregorian year (defaults to current)
     * @param int|null $month Gregorian month (defaults to current)
     * @param int|null $day Gregorian day (defaults to current)
     * @return array ['year' => 1404, 'month' => 11, 'day' => 22]
     */
    public static function gregorianToPersian(?int $year = null, ?int $month = null, ?int $day = null): array
    {
        $year = $year ?? (int) date('Y');
        $month = $month ?? (int) date('m');
        $day = $day ?? (int) date('d');

        $g_d_m = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
        
        $gy = $year - 1600;
        $gm = $month - 1;
        $gd = $day - 1;
        
        $g_day_no = 365 * $gy + (int) (($gy + 3) / 4) - (int) (($gy + 99) / 100) + (int) (($gy + 399) / 400);
        
        for ($i = 0; $i < $gm; ++$i) {
            $g_day_no += $g_d_m[$i + 1] - $g_d_m[$i];
        }
        
        if ($gm > 1 && (($gy % 4 == 0 && $gy % 100 != 0) || ($gy % 400 == 0))) {
            $g_day_no++;
        }
        
        $g_day_no += $gd;
        
        $j_day_no = $g_day_no - 79;
        
        $j_np = (int) ($j_day_no / 12053);
        $j_day_no = $j_day_no % 12053;
        
        $jy = 979 + 33 * $j_np + 4 * (int) ($j_day_no / 1461);
        
        $j_day_no %= 1461;
        
        if ($j_day_no >= 366) {
            $jy += (int) (($j_day_no - 1) / 365);
            $j_day_no = ($j_day_no - 1) % 365;
        }
        
        $j_d_m = [0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366];
        
        for ($i = 0; $i < 12 && $j_day_no >= $j_d_m[$i + 1]; $i++);
        
        $jm = $i + 1;
        $jd = $j_day_no - $j_d_m[$i] + 1;
        
        return [
            'year' => $jy,
            'month' => $jm,
            'day' => $jd,
        ];
    }

    /**
     * Get Persian date as formatted string
     * 
     * @param string $format Format string (Y = year, m = month with leading zero, d = day with leading zero)
     * @param int|null $timestamp Unix timestamp (defaults to current time)
     * @return string
     */
    public static function persianDate(string $format = 'Ymd', ?int $timestamp = null): string
    {
        $timestamp = $timestamp ?? time();
        
        $year = (int) date('Y', $timestamp);
        $month = (int) date('m', $timestamp);
        $day = (int) date('d', $timestamp);
        
        $persian = self::gregorianToPersian($year, $month, $day);
        
        $result = $format;
        $result = str_replace('Y', $persian['year'], $result);
        $result = str_replace('m', str_pad($persian['month'], 2, '0', STR_PAD_LEFT), $result);
        $result = str_replace('d', str_pad($persian['day'], 2, '0', STR_PAD_LEFT), $result);
        $result = str_replace('n', $persian['month'], $result);
        $result = str_replace('j', $persian['day'], $result);
        
        return $result;
    }

    /**
     * Get today's Persian date in YYYYMMDD format
     * 
     * @return string e.g., "14041122"
     */
    public static function todayPersian(): string
    {
        return self::persianDate('Ymd');
    }
}
