<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Activity extends Model
{
    /** @use HasFactory<\Database\Factories\ActivityFactory> */
    use HasFactory;

    use SoftDeletes;

    protected $fillable = [
        'due_date',
        'call_back_at',
        'amount',
        'note',
        'action_id',
        'user_id',
        'decision_id',
        'contract_id',
        'client_case_id',
    ];

    /*protected function casts(): array
    {
        return [
            'call_back_at' => 'datetime',
        ];
    }*/

    protected $hidden = [
        'action_id',
        'decision_id',
        'client_case_id',
        'user_id',
        'contract_id',
    ];

    protected static function booted()
    {
        static::creating(function (Activity $activity) {
            if (! isset($activity->user_id)) {
                $activity->user_id = auth()->id();
            }

            // If an activity with a due date is added for a contract, update the related account's promise_date
            if (! empty($activity->contract_id) && ! empty($activity->due_date)) {
                \App\Models\Account::query()
                    ->where('contract_id', $activity->contract_id)
                    ->update(
                        ['promise_date' => $activity->due_date, 'updated_at' => now()],
                    );
            }
        });

        static::created(function (Activity $activity) {
            if (! empty($activity->decision_id)) {
                event(new \App\Events\ActivityDecisionApplied($activity));
            }
        });
    }

    /**
     * Scope activities to those linked to contracts within a specific segment.
     */
    #[Scope]
    public function scopeForSegment(Builder $query, int $segmentId, array $contractIds): Builder
    {
        return $query->where(function ($q) use ($contractIds) {
            $q->whereNull('contract_id');
            if (! empty($contractIds)) {
                $q->orWhereIn('contract_id', $contractIds);
            }
        });
    }

    /**
     * Scope activities with decoded base64 filters.
     */
    #[Scope]
    public function scopeWithFilters(Builder $query, ?string $encodedFilters, \App\Models\ClientCase $clientCase): Builder
    {
        if (empty($encodedFilters)) {
            return $query;
        }

        try {
            $decompressed = base64_decode($encodedFilters);
            $filters = json_decode($decompressed, true);

            if (! is_array($filters)) {
                return $query;
            }

            if (! empty($filters['action_id'])) {
                $query->where('action_id', $filters['action_id']);
            }

            if (! empty($filters['contract_uuid'])) {
                $contract = $clientCase->contracts()->where('uuid', $filters['contract_uuid'])->first(['id']);
                if ($contract) {
                    $query->where('contract_id', $contract->id);
                }
            }

            if (! empty($filters['user_id'])) {
                $query->where('user_id', $filters['user_id']);
            }

            if (! empty($filters['date_from'])) {
                $query->whereDate('created_at', '>=', $filters['date_from']);
            }

            if (! empty($filters['date_to'])) {
                $query->whereDate('created_at', '<=', $filters['date_to']);
            }
        } catch (\Throwable $e) {
            \Log::error('Invalid activity filter format', [
                'error' => $e->getMessage(),
            ]);
        }

        return $query;
    }

    public function action(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Action::class);
    }

    public function decision(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Decision::class);
    }

    public function clientCase(): BelongsTo
    {
        return $this->belongsTo(\App\Models\ClientCase::class);
    }

    public function contract(): ?BelongsTo
    {
        return $this->belongsTo(\App\Models\Contract::class);
    }

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

    public function callLaters(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(\App\Models\CallLater::class);
    }

    public function emailLogs(): BelongsToMany
    {
        return $this->belongsToMany(EmailLog::class, 'activity_email_logs');
    }
}
