<?php

namespace App\Jobs;

use App\Models\ClientCase;
use App\Models\SmsProfile;
use App\Models\SmsSender;
use App\Models\SmsTemplate;
use App\Services\Sms\SmsService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Redis;

class SendSmsJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     */
    public function __construct(
        public int $profileId,
        public string $to,
        public string $content,
        public ?int $senderId = null,
        public ?string $countryCode = null,
        public bool $deliveryReport = false,
        public ?string $clientReference = null,
        // For optional activity creation (case UI only)
        public ?int $templateId = null,
        public ?int $clientCaseId = null,
        public ?int $userId = null,
        // If provided, update this activity on failure instead of creating a new one
        public ?int $activityId = null,
    ) {}

    /**
     * Execute the job.
     */
    public function handle(SmsService $sms): void
    {
        // Resolve models
        /** @var SmsProfile|null $profile */
        $profile = SmsProfile::find($this->profileId);
        if (! $profile) {
            return; // nothing to do
        }

        /** @var SmsSender|null $sender */
        $sender = $this->senderId ? SmsSender::find($this->senderId) : null;

        // Apply Redis throttle from config to avoid provider rate limits
        $scope = config('services.sms.throttle.scope', 'global');
        $provider = config('services.sms.throttle.provider_key', 'smsapi_si');
        $allow = (int) config('services.sms.throttle.allow', 30);
        $every = (int) config('services.sms.throttle.every', 60);
        $jitter = (int) config('services.sms.throttle.jitter_seconds', 2);
        $key = $scope === 'per_profile' && $profile ? "sms:{$provider}:{$profile->id}" : "sms:{$provider}";

        $log = null;
        try {
            Redis::throttle($key)->allow($allow)->every($every)->then(function () use (&$log, $sms, $profile, $sender) {
                // Send and get log (handles queued->sent/failed transitions internally)
                $log = $sms->sendRaw(
                    profile: $profile,
                    to: $this->to,
                    content: $this->content,
                    sender: $sender,
                    countryCode: $this->countryCode,
                    deliveryReport: $this->deliveryReport,
                    clientReference: $this->clientReference,
                );
            }, function () use ($jitter) {
                return $this->release(max(1, rand(1, $jitter)));
            });
        } catch (\Throwable $e) {
            // Fallback if Redis is unavailable in test or local env
            $log = $sms->sendRaw(
                profile: $profile,
                to: $this->to,
                content: $this->content,
                sender: $sender,
                countryCode: $this->countryCode,
                deliveryReport: $this->deliveryReport,
                clientReference: $this->clientReference,
            );
        }
        // Update an existing pre-created activity ONLY on failure when activityId is provided
        if ($this->activityId && $log && ($log->status === 'failed')) {
            try {
                $activity = \App\Models\Activity::find($this->activityId);
                if ($activity) {
                    $note = (string) ($activity->note ?? '');
                    $append = sprintf(
                        ' | Napaka: %s',
                        'SMS ni bil poslan!'
                    );
                    $activity->update(['note' => $note.$append]);
                }
            } catch (\Throwable $e) {
                \Log::warning('SendSmsJob activity update failed', [
                    'error' => $e->getMessage(),
                    'activity_id' => $this->activityId,
                ]);
            }
        }

        // If no pre-created activity is provided and invoked from the case UI with a selected template, create an Activity
        if (! $this->activityId && $this->templateId && $this->clientCaseId && $log) {
            try {
                /** @var SmsTemplate|null $template */
                $template = SmsTemplate::find($this->templateId);
                /** @var ClientCase|null $case */
                $case = ClientCase::find($this->clientCaseId);
                if ($template && $case) {
                    $note = '';
                    if ($log->status === 'sent') {
                        $note = sprintf('Tel: %s | Telo: %s', (string) $this->to, (string) $this->content);
                    } elseif ($log->status === 'failed') {
                        $note = sprintf(
                            'Tel: %s | Telo: %s | Napaka: %s',
                            (string) $this->to,
                            (string) $this->content,
                            'SMS ni bil poslan!'
                        );
                    }

                    $case->activities()->create([
                        'note' => $note,
                        'action_id' => $template->action_id,
                        'decision_id' => $template->decision_id,
                        'user_id' => $this->userId,
                    ]);
                }

            } catch (\Throwable $e) {
                \Log::warning('SendSmsJob activity creation failed', [
                    'error' => $e->getMessage(),
                    'client_case_id' => $this->clientCaseId,
                    'template_id' => $this->templateId,
                ]);
            }
        }

    }
}
