<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Carbon;

/**
 * @property int $id
 * @property int $basic_basket_product_id
 * @property int $store_id
 * @property string $slug
 * @property string $name
 * @property string $provider
 * @property string $search_query
 * @property string|null $expected_url
 * @property string|null $store_product_url
 * @property array<array-key, mixed>|null $expected_url_contains
 * @property int|null $expected_rank_group
 * @property string|null $expected_data_docid
 * @property string|null $expected_product_id
 * @property string|null $expected_gid
 * @property array<array-key, mixed>|null $expected_shopping_url_contains
 * @property string|null $expected_title
 * @property string|null $expected_seller
 * @property string|null $expected_domain
 * @property int|null $expected_position
 * @property array<array-key, mixed>|null $required_keywords
 * @property array<array-key, mixed>|null $optional_keywords
 * @property array<array-key, mixed>|null $negative_keywords
 * @property string $selection_strategy
 * @property int $min_match_score
 * @property string|null $location_name
 * @property string|null $language_code
 * @property bool $is_active
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property-read Collection<int, PriceObservationFailure> $failures
 * @property-read int|null $failures_count
 * @property-read PriceObservation|null $latestObservation
 * @property-read Collection<int, PriceObservation> $observations
 * @property-read int|null $observations_count
 * @property-read BasicBasketProduct $product
 * @property-read Store $store
 * @property-read Collection<int, PriceSyncTask> $tasks
 * @property-read int|null $tasks_count
 *
 * @method static Builder<static>|StoreProductTarget active()
 * @method static \Database\Factories\StoreProductTargetFactory factory($count = null, $state = [])
 * @method static Builder<static>|StoreProductTarget newModelQuery()
 * @method static Builder<static>|StoreProductTarget newQuery()
 * @method static Builder<static>|StoreProductTarget query()
 * @method static Builder<static>|StoreProductTarget whereBasicBasketProductId($value)
 * @method static Builder<static>|StoreProductTarget whereCreatedAt($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedDataDocid($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedDomain($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedGid($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedPosition($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedProductId($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedRankGroup($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedSeller($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedShoppingUrlContains($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedTitle($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedUrl($value)
 * @method static Builder<static>|StoreProductTarget whereExpectedUrlContains($value)
 * @method static Builder<static>|StoreProductTarget whereId($value)
 * @method static Builder<static>|StoreProductTarget whereIsActive($value)
 * @method static Builder<static>|StoreProductTarget whereLanguageCode($value)
 * @method static Builder<static>|StoreProductTarget whereLocationName($value)
 * @method static Builder<static>|StoreProductTarget whereMinMatchScore($value)
 * @method static Builder<static>|StoreProductTarget whereName($value)
 * @method static Builder<static>|StoreProductTarget whereNegativeKeywords($value)
 * @method static Builder<static>|StoreProductTarget whereOptionalKeywords($value)
 * @method static Builder<static>|StoreProductTarget whereProvider($value)
 * @method static Builder<static>|StoreProductTarget whereRequiredKeywords($value)
 * @method static Builder<static>|StoreProductTarget whereSearchQuery($value)
 * @method static Builder<static>|StoreProductTarget whereSelectionStrategy($value)
 * @method static Builder<static>|StoreProductTarget whereSlug($value)
 * @method static Builder<static>|StoreProductTarget whereStoreId($value)
 * @method static Builder<static>|StoreProductTarget whereUpdatedAt($value)
 *
 * @mixin \Eloquent
 */
class StoreProductTarget extends Model
{
    use HasFactory;

    /**
     * @var list<string>
     */
    protected $fillable = [
        'basic_basket_product_id',
        'store_id',
        'slug',
        'name',
        'provider',
        'search_query',
        'expected_url',
        'store_product_url',
        'expected_url_contains',
        'expected_title',
        'expected_seller',
        'expected_domain',
        'expected_position',
        'expected_rank_group',
        'expected_data_docid',
        'expected_product_id',
        'expected_gid',
        'expected_shopping_url_contains',
        'required_keywords',
        'optional_keywords',
        'negative_keywords',
        'selection_strategy',
        'min_match_score',
        'location_name',
        'language_code',
        'is_active',
    ];

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'expected_url_contains' => 'array',
            'expected_rank_group' => 'integer',
            'expected_shopping_url_contains' => 'array',
            'required_keywords' => 'array',
            'optional_keywords' => 'array',
            'negative_keywords' => 'array',
            'expected_position' => 'integer',
            'min_match_score' => 'integer',
            'is_active' => 'boolean',
        ];
    }

    public function scopeActive(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(BasicBasketProduct::class, 'basic_basket_product_id');
    }

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

    public function tasks(): HasMany
    {
        return $this->hasMany(PriceSyncTask::class);
    }

    public function observations(): HasMany
    {
        return $this->hasMany(PriceObservation::class);
    }

    public function latestObservation(): HasOne
    {
        return $this->hasOne(PriceObservation::class)->latestOfMany('observed_at');
    }

    public function failures(): HasMany
    {
        return $this->hasMany(PriceObservationFailure::class);
    }
}
