<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AdminActivityLog;
use App\Models\Application;
use App\Models\Applicant;
use App\Models\JobListing;
use App\Services\NotificationService;
use Illuminate\Http\Request;

class ApplicationController extends Controller
{
    /**
     * Cancel all conflicting scheduled notifications when admin changes status.
     * Centralised to avoid duplication between updateStatus() and bulkUpdate().
     */
    private function cancelConflictingNotifications(Application $application, string $newStatus): void
    {
        // Cancel ALL scheduled stage_passed and stage_form_filled notifications
        // (admin intervened manually, auto-advance flow is no longer relevant)
        \App\Models\NotificationLog::where('application_id', $application->id)
            ->where('status', 'scheduled')
            ->where(function ($q) {
                $q->where('type', 'like', 'stage%_passed')
                  ->orWhere('type', 'like', 'stage%_form_filled');
            })
            ->update(['status' => 'cancelled']);

        // If admin accepts, also cancel any scheduled rejected notifications
        if ($newStatus === 'accepted') {
            \App\Models\NotificationLog::where('application_id', $application->id)
                ->where('status', 'scheduled')
                ->where('type', 'rejected')
                ->update(['status' => 'cancelled']);
        } elseif ($newStatus === 'rejected') {
            // If admin rejects, also cancel any scheduled accepted notifications
            \App\Models\NotificationLog::where('application_id', $application->id)
                ->where('status', 'scheduled')
                ->where('type', 'accepted')
                ->update(['status' => 'cancelled']);
        }
    }

    public function index(Request $request)
    {
        $query = Application::with(['applicant', 'jobListing.stages'])->latest();

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

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

        if ($request->filled('search')) {
            $search = str_replace(['%', '_'], ['\%', '\_'], $request->search);
            $query->whereHas('applicant', function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%");
            });
        }

        $applications = $query->paginate(20);
        $jobs = JobListing::orderBy('title')->get();

        // Build dynamic status list from all active job stages
        $statuses = \App\Models\JobStage::where('is_active', true)
            ->orderBy('stage_number')
            ->get()
            ->flatMap(function ($stage) {
                return [
                    'stage' . $stage->stage_number . '_passed',
                    'stage' . $stage->stage_number . '_form_filled',
                ];
            })
            ->unique()
            ->values()
            ->toArray();

        return view('admin.applications.index', compact('applications', 'jobs', 'statuses'));
    }

    public function show(Application $application)
    {
        $application->load(['applicant', 'jobListing.stages', 'stageResponses.jobStage', 'notificationLogs']);

        // Build available statuses for this application based on job stages
        $availableStatuses = $this->getAvailableStatuses($application);

        // Pre-fetch pending rejection notification for the view (avoid DB query in Blade)
        $pendingRejectNotif = null;
        if ($application->status === 'rejected') {
            $pendingRejectNotif = \App\Models\NotificationLog::where('application_id', $application->id)
                ->where('type', 'rejected')
                ->where('status', 'scheduled')
                ->first();
        }

        return view('admin.applications.show', compact('application', 'availableStatuses', 'pendingRejectNotif'));
    }

    /**
     * Update application status — sends notification immediately
     */
    public function updateStatus(Request $request, Application $application)
    {
        $request->validate([
            'status' => [
                'required',
                'string',
                'max:50',
                'regex:/^(applied|stage\d+_passed|stage\d+_form_filled|accepted|rejected)$/',
            ],
            'admin_notes' => 'nullable|string',
        ]);

        $newStatus = $request->status;
        $oldStatus = $application->status;

        // Validate that stage number exists for this job
        if (preg_match('/^stage(\d+)/', $newStatus, $m)) {
            $stageNum = (int) $m[1];
            $stageExists = $application->jobListing->stages()
                ->where('stage_number', $stageNum)->exists();
            if (!$stageExists) {
                return back()->with('error', "Tahap {$stageNum} tidak ditemukan untuk lowongan ini.");
            }
        }

        // Build update data
        $updateData = [
            'status' => $newStatus,
            'admin_notes' => $request->admin_notes ?? $application->admin_notes,
        ];

        // Update current_stage for stage statuses
        if (preg_match('/^stage(\d+)/', $newStatus, $m)) {
            $updateData['current_stage'] = (int) $m[1];
        }

        // Update timestamps for final decisions
        if ($newStatus === 'accepted' || $newStatus === 'rejected') {
            $updateData['final_decision_at'] = now();
        }

        $application->update($updateData);

        // Cancel all conflicting scheduled notifications
        $this->cancelConflictingNotifications($application, $newStatus);

        // Send notification IMMEDIATELY (not scheduled)
        $notificationService = app(NotificationService::class);
        $notificationService->notifyStatusChange($application, $newStatus);

        $this->recordStatusChangeActivity($application, $oldStatus, $newStatus);

        return redirect()->route('admin.applications.show', $application)
            ->with('success', "Status berhasil diubah menjadi \"{$application->status_label}\". Notifikasi Email & WhatsApp telah dikirim.");
    }

    /**
     * Bulk update status (sends notifications immediately)
     */
    public function bulkUpdate(Request $request)
    {
        $request->validate([
            'application_ids' => 'required|array',
            'application_ids.*' => 'exists:applications,id',
            'status' => [
                'required',
                'string',
                'max:50',
                'regex:/^(applied|stage\d+_passed|stage\d+_form_filled|accepted|rejected)$/',
            ],
        ]);

        $notificationService = app(NotificationService::class);
        $count = 0;

        $applications = Application::whereIn('id', $request->application_ids)
            ->with(['applicant', 'jobListing'])
            ->get()
            ->keyBy('id');

        foreach ($request->application_ids as $id) {
            $application = $applications->get($id);
            if ($application) {
                $oldStatus = $application->status;
                $updateData = ['status' => $request->status];

                if (preg_match('/^stage(\d+)/', $request->status, $m)) {
                    $updateData['current_stage'] = (int) $m[1];
                }

                if ($request->status === 'accepted' || $request->status === 'rejected') {
                    $updateData['final_decision_at'] = now();
                }

                $application->update($updateData);

                // Cancel all conflicting scheduled notifications
                $this->cancelConflictingNotifications($application, $request->status);

                // Send notification immediately
                $notificationService->notifyStatusChange($application, $request->status);
                $this->recordStatusChangeActivity($application, $oldStatus, $request->status, true);
                $count++;
            }
        }

        return redirect()->route('admin.applications.index')
            ->with('success', "{$count} lamaran berhasil diperbarui. Notifikasi Email & WhatsApp telah dikirim.");
    }

    /**
     * Applicants list
     */
    public function applicants(Request $request)
    {
        $query = Applicant::withCount('applications')->latest();

        if ($request->filled('search')) {
            $search = str_replace(['%', '_'], ['\%', '\_'], $request->search);
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%")
                  ->orWhere('whatsapp', 'like', "%{$search}%");
            });
        }

        $applicants = $query->paginate(20);
        return view('admin.applicants.index', compact('applicants'));
    }

    /**
     * Download all applicants data as CSV or TXT
     */
    public function downloadApplicants(Request $request)
    {
        $format = $request->get('format', 'csv');

        if ($format === 'txt') {
            $content = "Nama\tEmail\tTelepon/WhatsApp\tTanggal Lahir\n";
            $content .= str_repeat('-', 80) . "\n";
            foreach (Applicant::orderBy('name')->cursor() as $a) {
                $content .= "{$a->name}\t{$a->email}\t{$a->whatsapp}\t" . ($a->birth_date ? $a->birth_date->format('Y-m-d') : '-') . "\n";
            }

            return response($content)
                ->header('Content-Type', 'text/plain')
                ->header('Content-Disposition', 'attachment; filename="data-pelamar-' . date('Y-m-d') . '.txt"');
        }

        // CSV — stream with cursor to avoid memory exhaustion
        $callback = function () {
            $file = fopen('php://output', 'w');
            // BOM for Excel UTF-8 compatibility
            fprintf($file, chr(0xEF) . chr(0xBB) . chr(0xBF));
            fputcsv($file, ['Nama', 'Email', 'Telepon/WhatsApp', 'Tanggal Lahir']);
            foreach (Applicant::orderBy('name')->cursor() as $a) {
                fputcsv($file, [
                    $a->name,
                    $a->email,
                    $a->whatsapp,
                    $a->birth_date ? $a->birth_date->format('Y-m-d') : '',
                ]);
            }
            fclose($file);
        };

        return response()->stream($callback, 200, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="data-pelamar-' . date('Y-m-d') . '.csv"',
        ]);
    }

    /**
     * Build available statuses for a given application based on its job's stages
     */
    private function getAvailableStatuses(Application $application): array
    {
        $stages = $application->jobListing->stages()->orderBy('stage_number')->get();

        $statuses = [
            ['value' => 'applied', 'label' => 'Lamaran Masuk'],
        ];

        foreach ($stages as $stage) {
            $statuses[] = [
                'value' => "stage{$stage->stage_number}_passed",
                'label' => "Lolos: {$stage->name}",
            ];
            $statuses[] = [
                'value' => "stage{$stage->stage_number}_form_filled",
                'label' => "Form Terisi: {$stage->name}",
            ];
        }

        $statuses[] = ['value' => 'accepted', 'label' => '★ TERIMA'];
        $statuses[] = ['value' => 'rejected', 'label' => '✕ TOLAK'];

        return $statuses;
    }

    /**
     * Record admin activity when application status is changed manually.
     */
    private function recordStatusChangeActivity(Application $application, string $oldStatus, string $newStatus, bool $isBulk = false): void
    {
        $application->loadMissing(['applicant:id,name', 'jobListing:id,title']);

        $applicantName = $application->applicant->name ?? 'Pelamar';
        $jobTitle = $application->jobListing->title ?? 'Lowongan';
        $actorName = auth()->user()->name ?? 'Admin';

        AdminActivityLog::record([
            'actor_user_id' => auth()->id(),
            'event_type' => $isBulk ? 'application_status_bulk_updated' : 'application_status_updated',
            'category' => 'admin',
            'title' => $isBulk ? 'Admin ubah status lamaran (bulk)' : 'Admin ubah status lamaran',
            'message' => $actorName . ' mengubah status ' . $applicantName . ' (' . $jobTitle . ') dari ' . $oldStatus . ' ke ' . $newStatus . '.',
            'url' => route('admin.applications.show', $application->id),
            'context' => [
                'application_id' => $application->id,
                'old_status' => $oldStatus,
                'new_status' => $newStatus,
                'bulk' => $isBulk,
            ],
        ]);
    }
}
