<?php

namespace App\DataTransferObjects;

use App\Models\Order;
use App\Models\Product;
use App\Models\ProductFile;
use Carbon\Carbon;
use Illuminate\Support\Str;

class DownloadableItem
{
    public function __construct(
        public Product $product,
        public Order $order,
        public ?ProductFile $latestVersion = null, // The actual latest version available globally
        public ?ProductFile $accessVersion = null,  // The latest version THIS user can access
        public int|string $status = 'active',
        public ?Carbon $supportExpiryDate = null,
        public ?string $licenseKey = null,
        public bool $isSubscription = false,
        public bool $hasPolicy = false,
        public mixed $purchasable = null,
        public ?Product $bundleProduct = null  // Set when this item is a child of a bundle
    ) {}

    /**
     * Determine if the user can download the SPECIFIC file/version.
     * If no version is passed, it checks if they have access to *any* version.
     */
    public function isAccessible(?ProductFile $targetVersion = null): bool
    {
        if ($this->isSubscription) {
             return $this->isActiveSubscription();
        }

        // 1. If policy is disabled, they have access to EVERYTHING.
        if (!$this->hasPolicy) {
            return true;
        }

        // 3. For one-time purchases with policy enabled:
        // They only get access if the file was released BEFORE their support expired.
        
        $target = $targetVersion ?? $this->accessVersion;

        if (!$target) {
            return false; // No file to access
        }

        // If the file has no release date, we assume it's accessible (or legacy)
        if (!$target->released_at) {
            return true;
        }

        // If support expiry is null (shouldn't happen if hasPolicy is true, but safety check)
        if (!$this->supportExpiryDate) {
            return true; 
        }

        // The Core Logic: Release Date <= Expiry Date
        // We use endOfDay() to be generous with the last day of support
        return $target->released_at->lessThanOrEqualTo($this->supportExpiryDate->endOfDay());
    }

    /**
     * Get the download URL for the latest accessible version.
     */
    /**
     * Get the download URL for the latest accessible version.
     */
    public function getDownloadUrl(?ProductFile $specificFile = null): ?string
    {
        $file = $specificFile ?? $this->accessVersion;

        if (!$file || !$this->isAccessible($file)) {
            return null;
        }
        
        $media = $file->getMedia('product_files')->first();
        
        if (!$media) {
            return null;
        }

        return \URL::signedRoute('download_attachment', ['id' => encrypt($media->id)]);
    }

    /**
     * Get all downloadable files for a specific version (or default to accessVersion).
     * Returns a collection of objects with name, size, type, and downloadUrl.
     */
    public function getFiles(?ProductFile $specificVersion = null): \Illuminate\Support\Collection
    {
        $version = $specificVersion ?? $this->accessVersion;

        if (!$version || !$this->isAccessible($version)) {
            return collect();
        }

        return $version->getMedia('product_files')->map(function ($media) {
            return (object) [
                'id' => $media->id,
                'name' => $media->filename . '.' . $media->extension,
                'size' => $media->readableSize(), 
                'downloadUrl' => \URL::signedRoute('download_attachment', ['id' => encrypt($media->id)]),
            ];
        });
    }

    public function getRefusalReason(): ?string
    {
        if ($this->isAccessible()) {
            return null;
        }

        if ($this->isSubscription) {
            return 'Subscription ' . getConstantLabel('subscription_status', $this->order->subscription->status);
        }

        return __('account.Support Expired');
    }

    public function hasNewerVersion(): bool
    {
        if (!$this->latestVersion || !$this->accessVersion) {
            return false;
        }
        
        return $this->latestVersion->id !== $this->accessVersion->id;
    }

    public function isActiveSubscription(): bool
    {
        return $this->isSubscription && in_array($this->status, [
            getConstant('SUBSCRIPTION_STATUS_ACTIVE'),
            getConstant('SUBSCRIPTION_STATUS_TRIAL')
        ]);
    }
    public function getRenewalPrice(): ?string
    {
        if (!$this->hasPolicy || !$this->product->supportPolicy || !$this->purchasable) {
            return null;
        }

        $policy = $this->product->supportPolicy;
        $originalPrice = $this->purchasable->price;

        // 1 = Percentage, 2 = Fixed Amount
        $price = $originalPrice;
        if ((int)$policy->discount_type === 1) {
            $price = $originalPrice * (1 - ($policy->discount_value / 100));
        } elseif ((int)$policy->discount_type === 2) {
            $price = max(0, $originalPrice - $policy->discount_value);
        }

        return ch_format_price($price);
    }

    public function getSupportDurationLabel(): string
    {
        if (!$this->hasPolicy || !$this->product->supportPolicy) {
            return 'support';
        }

        $policy = $this->product->supportPolicy;
        $d = $policy->support_duration;
        
        // 1=Days, 2=Weeks, 3=Months, 4=Years
        $unit = match((int)$policy->support_duration_unit) {
            1 => Str::plural('day', $d),
            2 => Str::plural('week', $d),
            3 => Str::plural('month', $d),
            4 => Str::plural('year', $d),
            default => 'days'
        };
        
        return "$d $unit";
    }
}
