<?php

namespace App\Console\Commands;

use App\Jobs\SendCampaignEmailJob;
use App\Models\Campaign;
use App\Services\CampaignRecipientResolver;
use App\Services\RecurringScheduleCalculator;
use Illuminate\Console\Command;

class DispatchRecurringCampaigns extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'campaigns:dispatch-recurring';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Fire any recurring email campaigns that are due, and advance their schedule';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $due = Campaign::query()
            ->where('type', 'recurring')
            ->where('status', 'active')
            ->whereNotNull('next_run_at')
            ->where('next_run_at', '<=', now())
            ->get();

        foreach ($due as $campaign) {
            $this->processCampaign($campaign);
        }

        $this->info("Processed {$due->count()} due recurring campaign(s).");

        return self::SUCCESS;
    }

    private function processCampaign(Campaign $template): void
    {
        $contactIds = CampaignRecipientResolver::resolve($template->recipients_config, $template->user_id);
        $count      = count($contactIds);

        // Materialize this occurrence as a real child campaign (snapshotting
        // the template's current content/targeting, not a live reference),
        // so it gets the exact same reporting/tracking/preview machinery as
        // any one-off campaign  CampaignEvent opens/clicks/bounces, the
        // analytics page, everything  for free.
        $occurrence = Campaign::create([
            'parent_id'         => $template->id,
            'type'              => 'recurring_occurrence',
            'title'             => $template->title . '  ' . now()->format('M j, Y g:i A'),
            'status'            => $this->initialOccurrenceStatus($template->auto_send, $count),
            'email_subject'     => $template->email_subject,
            'email_pre_header'  => $template->email_pre_header,
            'utm_status'        => $template->utm_status,
            'utm_source'        => $template->utm_source,
            'utm_medium'        => $template->utm_medium,
            'utm_campaign'      => $template->utm_campaign,
            'utm_term'          => $template->utm_term,
            'utm_content'       => $template->utm_content,
            'settings'          => $template->settings,
            'recipients_config' => $template->recipients_config,
            'recipients_count'  => $count,
            'created_by'        => $template->created_by,
            'user_id'           => $template->user_id,
        ]);

        if ($template->auto_send) {
            foreach ($contactIds as $contactId) {
                SendCampaignEmailJob::dispatch($occurrence->id, $contactId);
            }
        }

        $template->occurrences_sent += 1;
        $template->last_sent_at      = now();
        $template->recipients_count  = $count;

        $nextRun = RecurringScheduleCalculator::nextRunAt($template, now());
        $template->next_run_at = $nextRun;

        if (!$nextRun) {
            $template->status = 'paused';
        }

        $template->save();
    }

    private function initialOccurrenceStatus(bool $autoSend, int $recipientCount): string
    {
        if (!$autoSend) {
            return 'draft';
        }

        // Nothing to send  nothing will ever complete markCompleteIfDone(),
        // so mark it done immediately instead of leaving it stuck "sending".
        return $recipientCount > 0 ? 'sending' : 'sent';
    }
}
