<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class DiscountCode extends Model
{
    protected $fillable = [
        'code', 'type', 'value', 'scope', 'user_id',
        'min_order', 'max_uses', 'max_uses_per_user', 'used_count',
        'starts_at', 'expires_at', 'is_active',
    ];

    protected $casts = ['is_active' => 'boolean'];

    public function products(): BelongsToMany
    {
        return $this->belongsToMany(Product::class, 'discount_code_products');
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function isValid(): bool
    {
        if (!$this->is_active) return false;
        $today = self::todayJalali();
        if ($this->starts_at && $today < $this->starts_at) return false;
        if ($this->expires_at && $today > $this->expires_at) return false;
        if ($this->max_uses !== null && $this->used_count >= $this->max_uses) return false;
        return true;
    }

    public function isValidForUser(?int $userId): bool
    {
        if (!$this->isValid()) return false;
        if ($this->max_uses_per_user !== null && $userId) {
            $used = Order::where('coupon_code', $this->code)
                ->where('user_id', $userId)
                ->whereNotIn('status', ['failed', 'canceled'])
                ->count();
            if ($used >= $this->max_uses_per_user) return false;
        }
        return true;
    }

    public function formattedValue(): string
    {
        return $this->type === 'percent'
            ? $this->value . '%'
            : number_format($this->value) . ' تومان';
    }

    public function scopeLabel(): string
    {
        return match($this->scope) {
            'products' => 'محصولات خاص',
            'user'     => 'کاربر خاص',
            default    => 'همه محصولات',
        };
    }

    // ── Jalali helpers ────────────────────────────────────────────────────────

    public static function todayJalali(): string
    {
        return self::gregorianToJalali((int)date('Y'), (int)date('m'), (int)date('d'));
    }

    public static function gregorianToJalali(int $gy, int $gm, int $gd): string
    {
        $gMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
        $jMonths = [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29];

        $jy = $gy - 1600;
        $jm = $gm - 1;
        $jd = $gd - 1;

        $gDayNo = 365 * $jy
            + (int)(($jy + 3) / 4)
            - (int)(($jy + 99) / 100)
            + (int)(($jy + 399) / 400);

        for ($i = 0; $i < $jm; $i++) {
            $gDayNo += $gMonths[$i];
        }
        if ($jm > 1 && (($gy % 4 === 0 && $gy % 100 !== 0) || $gy % 400 === 0)) {
            $gDayNo++;
        }
        $gDayNo += $jd;

        $jDayNo = $gDayNo - 79;
        $jNp    = (int)($jDayNo / 12053);
        $jDayNo %= 12053;

        $jyOut  = 979 + 33 * $jNp + 4 * (int)($jDayNo / 1461);
        $jDayNo %= 1461;

        if ($jDayNo >= 366) {
            $jyOut  += (int)(($jDayNo - 1) / 365);
            $jDayNo  = ($jDayNo - 1) % 365;
        }

        $jmOut = 0;
        for ($i = 0; $i < 11 && $jDayNo >= $jMonths[$i]; $i++) {
            $jDayNo -= $jMonths[$i];
            $jmOut++;
        }
        $jmOut++;
        $jdOut = $jDayNo + 1;

        return sprintf('%04d/%02d/%02d', $jyOut, $jmOut, $jdOut);
    }
}
