<?php

declare(strict_types=1);

namespace App\Models;

use Database\Factories\DealFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * Сделка (лид) — основная транзакционная сущность.
 *
 * Tenant-aware модель с RLS: SELECT/INSERT/UPDATE/DELETE фильтруются
 * политикой `tenant_isolation` по `current_setting('app.current_tenant_id')`.
 *
 * Композитный PRIMARY KEY: (id, received_at). Таблица партиционирована
 * по received_at. Все save/update/delete операции должны включать
 * received_at в WHERE — иначе planner не сможет применить partition
 * pruning. Eloquent не поддерживает composite PK нативно, поэтому
 * setKeysForSaveQuery() переопределён.
 *
 * Идемпотентность webhook'ов реализована через отдельную таблицу
 * webhook_dedup_keys (v8.6, CTO-17): UNIQUE на партиционированной deals
 * без partition key невозможен. См. §5.5 narrative ТЗ.
 *
 * Источник: db/schema.sql v8.6 §5, table `deals`.
 *
 * @mixin IdeHelperDeal
 */
class Deal extends Model
{
    /** @use HasFactory<DealFactory> */
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'id',
        'tenant_id',
        'source_crm_id',
        'project_id',
        'phone',
        'phones',
        'status',
        'contact_name',
        'comment',
        'manager_id',
        'assigned_at',
        'escalated_count',
        'duplicate_of_id',
        'utm_source',
        'utm_medium',
        'utm_campaign',
        'utm_content',
        'region_code',
        'subject_code',
        'city',
        'time_in_form_seconds',
        'lead_score',
        'is_test',
        'received_at',
        'deleted_at',
        // Lead region resolution (Session 1, 31.05.2026).
        'phone_operator',
        'region_substituted',
    ];

    protected function casts(): array
    {
        return [
            'tenant_id' => 'integer',
            'source_crm_id' => 'integer',
            'project_id' => 'integer',
            'manager_id' => 'integer',
            'duplicate_of_id' => 'integer',
            'escalated_count' => 'integer',
            'time_in_form_seconds' => 'integer',
            'subject_code' => 'integer',
            'lead_score' => 'decimal:2',
            'phones' => 'array',
            'is_test' => 'boolean',
            'region_substituted' => 'boolean',
            'assigned_at' => 'datetime',
            'received_at' => 'datetime',
            'created_at' => 'datetime',
            'updated_at' => 'datetime',
            'deleted_at' => 'datetime',
        ];
    }

    /**
     * Composite PK: WHERE id = ? AND received_at = ? для save/update/delete.
     * Без переопределения Eloquent сгенерил бы только WHERE id = ?, что
     * заставило бы planner сканировать все партиции (partition pruning не работает).
     */
    protected function setKeysForSaveQuery($query)
    {
        return $query
            ->where('id', $this->getAttribute('id'))
            ->where('received_at', $this->getAttribute('received_at'));
    }

    /** @return BelongsTo<Tenant, $this> */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    /** @return BelongsTo<Project, $this> */
    public function project(): BelongsTo
    {
        return $this->belongsTo(Project::class);
    }

    /** @return BelongsTo<User, $this> */
    public function manager(): BelongsTo
    {
        return $this->belongsTo(User::class, 'manager_id');
    }
}
