<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    private const DEFAULT_IMAGE_PATH = 'images/default-banner.jpg';
    public const DELIVERY_ZONE_DHAKA_CITY = 'dhaka_city';
    public const DELIVERY_ZONE_SUB_DHAKA = 'sub_dhaka';
    public const DELIVERY_ZONE_OUT_DHAKA = 'out_dhaka';
    public const DEFAULT_DELIVERY_CHARGE_DHAKA_CITY = 80.00;
    public const DEFAULT_DELIVERY_CHARGE_SUB_DHAKA = 100.00;
    public const DEFAULT_DELIVERY_CHARGE_OUT_DHAKA = 130.00;
    public const BD_SIZES = [
        'XXS',
        'XS',
        'S',
        'M',
        'L',
        'XL',
        'XXL',
        '3XL',
        '4XL',
        '5XL',
        '28',
        '30',
        '32',
        '34',
        '36',
        '38',
        '40',
        '42',
        '44',
        '46',
        '48',
        '50',
    ];

    protected $fillable = [
        'category_id','title','slug','description',
        'admin_price','reseller_price','delivery_charge',
        'delivery_charge_dhaka_city','delivery_charge_sub_dhaka','delivery_charge_outside_dhaka',
        'delivery_payment_type','stock','delivery_time',
        'size','color','banner_photo','status',
        'vendor_profile_id','vendor_product_id',
    ];

    protected $casts = [
        'status' => 'boolean',
        'delivery_payment_type' => 'boolean',
        'admin_price' => 'decimal:2',
        'reseller_price' => 'decimal:2',
        'delivery_charge' => 'decimal:2',
        'delivery_charge_dhaka_city' => 'decimal:2',
        'delivery_charge_sub_dhaka' => 'decimal:2',
        'delivery_charge_outside_dhaka' => 'decimal:2',
        'vendor_profile_id' => 'integer',
        'vendor_product_id' => 'integer',
    ];

    public static function normalizeSizeOptions(array $sizes): string
    {
        $sizes = array_map(fn ($size) => trim((string) $size), $sizes);
        $sizes = array_values(array_unique(array_filter($sizes)));
        $sizes = array_values(array_filter($sizes, fn ($size) => in_array($size, self::BD_SIZES, true)));

        return implode(', ', $sizes);
    }

    public function getSizeOptionsAttribute(): array
    {
        $rawSize = trim((string) ($this->size ?? ''));
        if ($rawSize === '') {
            return [];
        }

        $sizes = preg_split('/\s*,\s*/', $rawSize) ?: [];
        $sizes = array_map(fn ($size) => trim((string) $size), $sizes);
        $sizes = array_values(array_unique(array_filter($sizes)));

        return array_values(array_filter($sizes, fn ($size) => in_array($size, self::BD_SIZES, true)));
    }

    public static function defaultDeliveryChargeForZone(?string $zone): float
    {
        return match ($zone) {
            self::DELIVERY_ZONE_DHAKA_CITY => self::DEFAULT_DELIVERY_CHARGE_DHAKA_CITY,
            self::DELIVERY_ZONE_SUB_DHAKA => self::DEFAULT_DELIVERY_CHARGE_SUB_DHAKA,
            default => self::DEFAULT_DELIVERY_CHARGE_OUT_DHAKA,
        };
    }

    public function hasConfiguredDeliveryCharges(): bool
    {
        return max(
            round((float) ($this->delivery_charge ?? 0), 2),
            round((float) ($this->delivery_charge_dhaka_city ?? 0), 2),
            round((float) ($this->delivery_charge_sub_dhaka ?? 0), 2),
            round((float) ($this->delivery_charge_outside_dhaka ?? 0), 2),
        ) > 0;
    }

    public function zoneDeliveryChargeInputValue(string $zone): float
    {
        if (!$this->hasConfiguredDeliveryCharges()) {
            return self::defaultDeliveryChargeForZone($zone);
        }

        $legacyCharge = round((float) ($this->delivery_charge ?? 0), 2);

        $zoneCharges = [
            self::DELIVERY_ZONE_DHAKA_CITY => $this->delivery_charge_dhaka_city,
            self::DELIVERY_ZONE_SUB_DHAKA => $this->delivery_charge_sub_dhaka,
            self::DELIVERY_ZONE_OUT_DHAKA => $this->delivery_charge_outside_dhaka,
        ];

        $charge = $zoneCharges[$zone] ?? null;
        if ($charge === null || $charge === '') {
            return $legacyCharge > 0 ? $legacyCharge : self::defaultDeliveryChargeForZone($zone);
        }

        return round((float) $charge, 2);
    }

    public function deliveryChargeForZone(?string $zone): float
    {
        if (!$this->hasConfiguredDeliveryCharges()) {
            return self::defaultDeliveryChargeForZone($zone);
        }

        return $this->zoneDeliveryChargeInputValue((string) $zone);
    }

    public function getBannerPhotoUrlAttribute()
    {
        if (!$this->banner_photo) {
            return asset(self::DEFAULT_IMAGE_PATH);
        }

        $path = trim((string) $this->banner_photo);
        if (preg_match('/^https?:\/\//i', $path)) {
            $managedAsset = $this->extractManagedAssetPath($path);
            if ($managedAsset !== null) {
                return $this->assetWithVersion($managedAsset);
            }

            if (request()->isSecure() && str_starts_with(strtolower($path), 'http://')) {
                return preg_replace('/^http:\/\//i', 'https://', $path, 1);
            }
            return $path;
        }

        return $this->resolveMediaUrl($path, asset(self::DEFAULT_IMAGE_PATH));
    }

    private function normalizeLegacyMediaPath(string $path): string
    {
        $clean = str_replace('\\', '/', trim($path));
        $clean = preg_replace('#/+#', '/', $clean);

        if (preg_match('#(?:^|/)(images/.*)$#i', $clean, $m)) {
            return ltrim($m[1], '/');
        }

        if (preg_match('#(?:^|/)(storage/.*)$#i', $clean, $m)) {
            return ltrim($m[1], '/');
        }

        return ltrim($clean, '/');
    }

    private function extractManagedAssetPath(string $path): ?string
    {
        $urlPath = (string) (parse_url($path, PHP_URL_PATH) ?: $path);
        $clean = str_replace('\\', '/', trim($urlPath));
        $clean = preg_replace('#/+#', '/', $clean);

        if (preg_match('#(?:^|/)(images/.*)$#i', $clean, $m)) {
            return ltrim($m[1], '/');
        }

        if (preg_match('#(?:^|/)(storage/.*)$#i', $clean, $m)) {
            return ltrim($m[1], '/');
        }

        return null;
    }

    private function resolveMediaUrl(string $path, string $fallback): string
    {
        $relative = $this->normalizeLegacyMediaPath($path);
        if ($relative === '') {
            return $fallback;
        }

        return $this->assetWithVersion($relative);
    }

    private function assetWithVersion(string $relative): string
    {
        $url = asset($relative);
        $mtime = $this->updated_at?->getTimestamp();
        if (!$mtime) {
            return $url;
        }
        return $url . '?v=' . $mtime;
    }

    public function category()
    {
        return $this->belongsTo(PdCategory::class, 'category_id');
    }

    public function images()
    {
        return $this->hasMany(ProductImage::class)->orderBy('sort_order')->orderBy('id');
    }

    public function scopeActive($q){ return $q->where('status',1); }
}
