<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AdminActivityLog;
use App\Models\JobListing;
use App\Models\NotificationLog;
use App\Services\NotificationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Process;

class NotificationController extends Controller
{
    /**
     * Queue stats (JSON) for realtime polling on queue page
     */
    public function queueStats()
    {
        return response()->json($this->buildQueueStats());
    }

    /**
     * Log Notifikasi - semua history
     */
    public function index(Request $request)
    {
        $query = NotificationLog::with(['application.applicant', 'application.jobListing'])->latest();

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('channel')) {
            $query->where('channel', $request->channel);
        }

        if ($request->filled('job_id')) {
            $query->whereHas('application', function ($q) use ($request) {
                $q->where('job_listing_id', $request->job_id);
            });
        }

        $logs = $query->paginate(30);
        $jobs = JobListing::orderBy('title')->get();
        return view('admin.notifications.index', compact('logs', 'jobs'));
    }

    /**
     * Antrian Notifikasi - pending/scheduled notifications
     */
    public function queue(Request $request)
    {
        $query = NotificationLog::with(['application.applicant', 'application.jobListing'])
            ->where('status', 'scheduled')
            ->orderBy('scheduled_at', 'asc');

        if ($request->filled('channel')) {
            $query->where('channel', $request->channel);
        }

        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        if ($request->filled('job_id')) {
            $query->whereHas('application', function ($q) use ($request) {
                $q->where('job_listing_id', $request->job_id);
            });
        }

        $pendingLogs = $query->paginate(30);

        // Count stats
        $stats = $this->buildQueueStats();

        $jobs = JobListing::orderBy('title')->get();
        return view('admin.notifications.queue', compact('pendingLogs', 'stats', 'jobs'));
    }

    /**
     * Cancel a scheduled notification
     */
    public function cancel(NotificationLog $notification)
    {
        if (!$notification->isCancellable()) {
            return back()->with('error', 'Notifikasi ini tidak dapat dibatalkan.');
        }

        $notification->loadMissing(['application.applicant:id,name,email,whatsapp', 'application.jobListing:id,title']);
        $target = $this->formatQueueTarget($notification);
        $actorName = auth()->user()->name ?? 'Admin';

        $notification->update(['status' => 'cancelled']);

        AdminActivityLog::record([
            'actor_user_id' => auth()->id(),
            'event_type' => 'queue_notification_cancelled',
            'category' => 'admin',
            'title' => 'Admin batalkan notifikasi antrian',
            'message' => $actorName . ' membatalkan notifikasi antrian ' . $target . '.',
            'url' => route('admin.notifications.queue'),
            'context' => [
                'notification_log_id' => $notification->id,
                'channel' => $notification->channel,
                'type' => $notification->type,
            ],
        ]);

        return back()->with('success', 'Notifikasi berhasil dibatalkan.');
    }

    /**
     * Send a scheduled notification immediately
     */
    public function sendNow(NotificationLog $notification)
    {
        if ($notification->status !== 'scheduled') {
            return back()->with('error', 'Notifikasi ini tidak dalam status dijadwalkan.');
        }

        $notification->loadMissing(['application.applicant:id,name', 'application.jobListing:id,title']);
        $target = $this->formatQueueTarget($notification);
        $actorName = auth()->user()->name ?? 'Admin';

        $service = app(NotificationService::class);
        $success = $service->processScheduledLog($notification);

        if ($success) {
            // Also advance application status when sent manually
            $service->advanceStatusForNotification($notification);

            AdminActivityLog::record([
                'actor_user_id' => auth()->id(),
                'event_type' => 'queue_notification_sent_manual',
                'category' => 'manual_send',
                'title' => 'Send Now manual berhasil',
                'message' => $actorName . ' mengirim manual notifikasi antrian ' . $target . '.',
                'url' => route('admin.notifications.queue'),
                'context' => [
                    'notification_log_id' => $notification->id,
                    'channel' => $notification->channel,
                    'type' => $notification->type,
                    'result' => 'sent',
                ],
            ]);

            return back()->with('success', 'Notifikasi berhasil dikirim dan status lamaran diperbarui.');
        }

        AdminActivityLog::record([
            'actor_user_id' => auth()->id(),
            'event_type' => 'queue_notification_sent_manual_failed',
            'category' => 'manual_send',
            'title' => 'Send Now manual gagal',
            'message' => $actorName . ' gagal mengirim manual notifikasi antrian ' . $target . '. Error: ' . ($notification->error ?: '-'),
            'url' => route('admin.notifications.queue'),
            'context' => [
                'notification_log_id' => $notification->id,
                'channel' => $notification->channel,
                'type' => $notification->type,
                'result' => 'failed',
                'error' => $notification->error,
            ],
        ]);

        return back()->with('error', 'Gagal mengirim notifikasi: ' . $notification->error);
    }

    /**
     * Send all due scheduled notifications now (dispatches to background process to avoid HTTP timeout)
     */
    public function sendAllDue(Request $request)
    {
        $dueCount = NotificationLog::readyToSend()->count();

        if ($dueCount === 0) {
            if ($request->expectsJson()) {
                return response()->json([
                    'status' => 'ok',
                    'due_count' => 0,
                    'message' => 'Tidak ada notifikasi yang perlu dikirim saat ini.',
                ]);
            }

            return back()->with('success', 'Tidak ada notifikasi yang perlu dikirim saat ini.');
        }

        // Run artisan command in background to avoid HTTP timeout
        $artisan = base_path('artisan');
        $php = PHP_BINARY ?: 'php';
        $command = escapeshellarg($php) . ' ' . escapeshellarg($artisan) . ' notifications:send-scheduled --no-interaction';
        $startedInBackground = false;

        try {
            Process::path(base_path())->start($command);
            $startedInBackground = true;
        } catch (\Throwable $e) {
            Log::warning('Failed to start background scheduled notifications process, using sync fallback.', [
                'error' => $e->getMessage(),
            ]);
        }

        if (!$startedInBackground) {
            Artisan::call('notifications:send-scheduled', ['--no-interaction' => true]);
        }

        if ($request->expectsJson()) {
            return response()->json([
                'status' => 'ok',
                'due_count' => $dueCount,
                'message' => $startedInBackground
                    ? "Proses pengiriman {$dueCount} notifikasi telah dimulai di background."
                    : "Proses pengiriman {$dueCount} notifikasi dijalankan langsung (sync fallback).",
            ]);
        }

        if ($startedInBackground) {
            return back()->with('success', "Proses pengiriman {$dueCount} notifikasi telah dimulai di background. Refresh halaman untuk melihat progress.");
        }

        return back()->with('success', "Proses pengiriman {$dueCount} notifikasi dijalankan langsung karena mode background tidak tersedia.");
    }

    /**
     * Build queue statistics payload used by both Blade view and JSON endpoint.
     */
    private function buildQueueStats(): array
    {
        return [
            'total_scheduled' => NotificationLog::where('status', 'scheduled')->count(),
            'email_scheduled' => NotificationLog::where('status', 'scheduled')->where('channel', 'email')->count(),
            'wa_scheduled' => NotificationLog::where('status', 'scheduled')->where('channel', 'whatsapp')->count(),
            'due_now' => NotificationLog::readyToSend()->count(),
        ];
    }

    /**
     * Cancel all scheduled notifications
     */
    public function cancelAll()
    {
        $count = NotificationLog::where('status', 'scheduled')->update(['status' => 'cancelled']);

        if ($count > 0) {
            $actorName = auth()->user()->name ?? 'Admin';
            AdminActivityLog::record([
                'actor_user_id' => auth()->id(),
                'event_type' => 'queue_notification_cancelled_all',
                'category' => 'admin',
                'title' => 'Admin batalkan semua antrian',
                'message' => $actorName . ' membatalkan ' . $count . ' notifikasi dari antrian.',
                'url' => route('admin.notifications.queue'),
                'context' => [
                    'cancelled_count' => $count,
                ],
            ]);
        }

        return back()->with('success', "{$count} notifikasi berhasil dibatalkan.");
    }

    /**
     * Reschedule a notification to a new time
     */
    public function reschedule(Request $request, NotificationLog $notification)
    {
        $request->validate([
            'scheduled_at' => 'required|date|after:now',
        ]);

        if ($notification->status !== 'scheduled') {
            return back()->with('error', 'Notifikasi ini tidak dalam status dijadwalkan.');
        }

        $notification->loadMissing(['application.applicant:id,name', 'application.jobListing:id,title']);
        $oldSchedule = $notification->scheduled_at?->copy();
        $target = $this->formatQueueTarget($notification);
        $actorName = auth()->user()->name ?? 'Admin';

        $notification->update(['scheduled_at' => $request->scheduled_at]);

        AdminActivityLog::record([
            'actor_user_id' => auth()->id(),
            'event_type' => 'queue_notification_rescheduled',
            'category' => 'admin',
            'title' => 'Admin reschedule notifikasi antrian',
            'message' => $actorName . ' mengubah jadwal notifikasi antrian ' . $target . ' dari '
                . ($oldSchedule?->format('d/m/Y H:i') ?? '-')
                . ' ke '
                . ($notification->scheduled_at?->format('d/m/Y H:i') ?? '-')
                . '.',
            'url' => route('admin.notifications.queue'),
            'context' => [
                'notification_log_id' => $notification->id,
                'old_scheduled_at' => $oldSchedule?->toIso8601String(),
                'new_scheduled_at' => $notification->scheduled_at?->toIso8601String(),
            ],
        ]);

        return back()->with('success', 'Jadwal notifikasi berhasil diubah.');
    }

    /**
     * Format queue notification target text for admin activity messages.
     */
    private function formatQueueTarget(NotificationLog $notification): string
    {
        $application = $notification->application;
        $recipient = $notification->recipient_name
            ?: ($application?->applicant?->name ?? 'pelamar');
        $jobTitle = $application?->jobListing?->title ?? 'lowongan';
        $channel = $notification->channel === 'email' ? 'Email' : 'WhatsApp';

        return $channel . ' [' . $notification->type . '] untuk ' . $recipient . ' (' . $jobTitle . ')';
    }
}
