<?php

namespace App\Console\Commands;

use App\Models\Application;
use App\Models\JobListing;
use App\Models\NotificationLog;
use App\Models\Setting;
use App\Services\NotificationService;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;

class ProcessAutoAdvance extends Command
{
    protected $signature = 'applications:auto-advance';
    protected $description = 'Automatically advance application stages based on configured delays and form completion';

    /**
     * Flow per application (N = jumlah stage aktif):
     *
     *   H+0                       : Klik Melamar → Notif 1 (Lamaran Diterima) — langsung saat apply
     *   H+(interval) dari apply   : Auto → schedule stage1_passed notif → dikirim → status berubah
     *   User isi form 1           : → stage1_form_filled → Notif (Formulir 1 Diterima) — langsung
     *   H+(interval) dari form 1  : Auto → schedule stage2_passed notif → dikirim → status berubah
     *   User isi form 2           : → stage2_form_filled → Notif (Formulir 2 Diterima) — langsung
     *   ...
     *   H+(interval) dari form N  : Auto → schedule final_auto_decision notif
     *                               Untuk rejected: notif dijadwalkan H+interval hari, status berubah saat terkirim
     *                               Untuk accepted: notif dijadwalkan segera
     *
     * PENTING:
     * - Command ini HANYA menjadwalkan notifikasi, TIDAK mengubah status langsung.
     * - Status diubah oleh ProcessScheduledNotifications → advanceStatusForNotification().
     * - Untuk rejected: status tetap form_filled sampai notifikasi terkirim (admin punya waktu review).
     * - Admin bisa override ke accepted sebelum notifikasi rejected terkirim.
     * - Interval dihitung dari waktu submit form (bukan dari applied_at).
     *
     */
    public function handle(): int
    {
        $autoAdvance = Setting::get('auto_advance', '0');

        if ($autoAdvance !== '1') {
            return 0;
        }

        $intervalDays = (int) Setting::get('stage_advance_days', 2);
        $notificationService = app(NotificationService::class);
        $totalAdvanced = 0;

        $jobs = JobListing::where('is_active', true)->with('stages')->get();

        foreach ($jobs as $job) {
            $stages = $job->stages()->where('is_active', true)->orderBy('stage_number')->get();
            if ($stages->isEmpty()) continue;

            $applications = Application::where('job_listing_id', $job->id)
                ->whereNotIn('status', ['accepted', 'rejected'])
                ->whereNotNull('applied_at')
                ->with('stageResponses')
                ->get();

            foreach ($applications as $application) {
              try {
                $status = $application->status;
                $nextStatus = null;
                $referenceTime = null;

                if ($status === 'applied') {
                    // Can advance to stage1_passed after interval from apply time
                    $referenceTime = Carbon::parse($application->applied_at);
                    $nextStatus = 'stage' . $stages->first()->stage_number . '_passed';

                } elseif (preg_match('/^stage(\d+)_form_filled$/', $status, $m)) {
                    // User filled form N → can advance to stageN+1_passed after interval from form submit
                    $currentStageNum = (int) $m[1];
                    $currentStage = $stages->first(fn($s) => $s->stage_number === $currentStageNum);
                    $nextStage = $stages->first(fn($s) => $s->stage_number > $currentStageNum);

                    // Get the form submission time as reference
                    $stageResponse = $application->stageResponses
                        ->first(fn($r) => $r->job_stage_id === $currentStage?->id);
                    $referenceTime = $stageResponse
                        ? Carbon::parse($stageResponse->submitted_at ?? $stageResponse->created_at)
                        : null;

                    if ($nextStage) {
                        $nextStatus = 'stage' . $nextStage->stage_number . '_passed';
                    } else {
                        // All stages done → auto-decide based on setting
                        $nextStatus = Setting::get('final_auto_decision', 'rejected');
                    }

                } elseif (preg_match('/^stage(\d+)_passed$/', $status, $m)) {
                    // User at stageN_passed but hasn't filled form → do NOT advance
                    // Check if this stage has form_fields; if no form, treat as auto-filled
                    $currentStageNum = (int) $m[1];
                    $currentStage = $stages->first(fn($s) => $s->stage_number === $currentStageNum);

                    if ($currentStage && empty($currentStage->form_fields)) {
                        // Stage has no form → can advance like form_filled
                        $nextStage = $stages->first(fn($s) => $s->stage_number > $currentStageNum);

                        // Reference time = when they reached this stage (use notification sent_at or now)
                        $stageNotif = NotificationLog::where('application_id', $application->id)
                            ->where('type', "stage{$currentStageNum}_passed")
                            ->where('status', 'sent')
                            ->first();
                        $referenceTime = $stageNotif
                            ? Carbon::parse($stageNotif->sent_at)
                            : Carbon::parse($application->updated_at); // Fallback to last update time

                        if ($nextStage) {
                            $nextStatus = 'stage' . $nextStage->stage_number . '_passed';
                        } else {
                            // All stages done → auto-decide based on setting
                            $nextStatus = Setting::get('final_auto_decision', 'rejected');
                        }
                    }
                    // If stage has forms → $nextStatus stays null, skip this application
                }

                // Skip if no valid next step or no reference time
                if (!$nextStatus || !$referenceTime) continue;

                // Check if enough time has passed since reference time
                if ($referenceTime->copy()->addDays($intervalDays)->isFuture()) continue;

                // Check if notification already exists
                $alreadyExists = NotificationLog::where('application_id', $application->id)
                    ->where('type', $nextStatus)
                    ->whereIn('status', ['scheduled', 'sent'])
                    ->exists();

                // Skip if already processed (notification already exists)
                if ($alreadyExists) continue;

                // DO NOT update status directly here.
                // Status will be advanced by advanceStatusForNotification()
                // when the notification is actually sent by ProcessScheduledNotifications.
                // This prevents race conditions and ensures:
                // - For rejected: applicant doesn't see "rejected" prematurely
                //   (admin gets review window before notification + status change)
                // - For stage_passed: status changes when notification is sent (~1 min)

                // Schedule notification based on status type
                if ($nextStatus === 'rejected') {
                    // Auto-reject: schedule notifikasi H+interval hari dari sekarang
                    // Admin bisa membatalkan dan mengubah ke accepted sebelum notif terkirim
                    // Status akan berubah ke rejected ketika notifikasi benar-benar dikirim
                    $rejectNotifAt = Carbon::now()->addDays($intervalDays);
                    $notificationService->scheduleStatusChange($application, $nextStatus, $rejectNotifAt);
                } elseif ($nextStatus === 'accepted') {
                    // Auto-accept via final_auto_decision setting
                    // Schedule notifikasi diterima segera (ProcessScheduledNotifications will send + advance)
                    $notificationService->scheduleStatusChange($application, $nextStatus, now());
                } else {
                    // Stage passed: schedule notifikasi segera
                    $notificationService->scheduleStatusChange($application, $nextStatus, now());
                }

                $totalAdvanced++;
              } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error("ProcessAutoAdvance exception for application #{$application->id}: {$e->getMessage()}");
              }
            }
        }

        if ($totalAdvanced > 0) {
            $this->info("Auto-advanced {$totalAdvanced} application(s).");
        }

        return 0;
    }
}
