<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AdminActivityLog;
use App\Models\Applicant;
use App\Models\Application;
use App\Models\NotificationLog;
use Carbon\Carbon;
use Illuminate\Http\Request;

class ActivityController extends Controller
{
    /**
     * Return recent admin activity feed for bell dropdown.
     */
    public function feed(Request $request)
    {
        $limit = (int) $request->query('limit', 20);
        $limit = max(8, min($limit, 50));

        $lastSeenAt = $this->getLastSeenAt(true);
        $items = $this->buildActivityItems($limit, $lastSeenAt);
        $unreadCount = $this->calculateUnreadCount($lastSeenAt);

        return response()->json([
            'unread_count' => $unreadCount,
            'last_seen_at' => $lastSeenAt?->toIso8601String(),
            'server_time' => now()->toIso8601String(),
            'items' => $items,
        ]);
    }

    /**
     * Mark all activity as read for the current admin account.
     */
    public function markRead()
    {
        $now = now();
        $user = auth()->user();

        if ($user) {
            $user->forceFill([
                'admin_activity_last_seen_at' => $now,
            ])->saveQuietly();
        }

        return response()->json([
            'status' => 'ok',
            'message' => 'Aktivitas ditandai sudah dibaca.',
            'last_seen_at' => $now->toIso8601String(),
        ]);
    }

    /**
     * Build merged timeline from applicant, application, and sent queue notifications.
     */
    private function buildActivityItems(int $limit, ?Carbon $lastSeenAt = null): array
    {
        $items = [];

        $applicants = Applicant::query()
            ->latest('created_at')
            ->limit($limit)
            ->get(['id', 'name', 'email', 'created_at']);

        foreach ($applicants as $applicant) {
            $occurredAt = $applicant->created_at ?? now();

            $items[] = [
                'id' => 'applicant-' . $applicant->id,
                'category' => 'pelamar',
                'title' => 'Pelamar baru terdaftar',
                'message' => ($applicant->name ?: 'Pelamar') . ' baru membuat akun.',
                'time_human' => $occurredAt->locale('id')->diffForHumans(),
                'timestamp' => $occurredAt->toIso8601String(),
                'url' => route('admin.applicants', ['search' => $applicant->email]),
                'is_unread' => $lastSeenAt ? $occurredAt->gt($lastSeenAt) : true,
                'sort_at' => $occurredAt->timestamp,
            ];
        }

        $applications = Application::query()
            ->with(['applicant:id,name,email', 'jobListing:id,title'])
            ->latest('created_at')
            ->limit($limit)
            ->get(['id', 'applicant_id', 'job_listing_id', 'created_at']);

        foreach ($applications as $application) {
            $occurredAt = $application->created_at ?? now();
            $applicantName = $application->applicant->name ?? 'Pelamar';
            $jobTitle = $application->jobListing->title ?? 'Lowongan';

            $items[] = [
                'id' => 'application-' . $application->id,
                'category' => 'lamaran',
                'title' => 'Lamaran baru masuk',
                'message' => $applicantName . ' melamar untuk ' . $jobTitle . '.',
                'time_human' => $occurredAt->locale('id')->diffForHumans(),
                'timestamp' => $occurredAt->toIso8601String(),
                'url' => route('admin.applications.show', $application->id),
                'is_unread' => $lastSeenAt ? $occurredAt->gt($lastSeenAt) : true,
                'sort_at' => $occurredAt->timestamp,
            ];
        }

        $sentQueueLogs = NotificationLog::query()
            ->where('status', 'sent')
            ->whereNotNull('scheduled_at')
            ->whereNotNull('sent_at')
            ->with(['application.applicant:id,name', 'application.jobListing:id,title'])
            ->latest('sent_at')
            ->limit($limit)
            ->get(['id', 'application_id', 'type', 'channel', 'recipient_name', 'sent_at', 'scheduled_at']);

        foreach ($sentQueueLogs as $log) {
            $occurredAt = $log->sent_at ?? now();
            $recipient = $log->recipient_name
                ?: ($log->application->applicant->name ?? 'pelamar');
            $channelLabel = $log->channel === 'email' ? 'Email' : 'WhatsApp';
            $jobTitle = $log->application->jobListing->title ?? 'Lowongan';

            $items[] = [
                'id' => 'queue-sent-' . $log->id,
                'category' => 'antrian',
                'title' => 'Notifikasi antrian terkirim',
                'message' => $channelLabel . ' untuk ' . $jobTitle . ' terkirim ke ' . $recipient . '.',
                'time_human' => $occurredAt->locale('id')->diffForHumans(),
                'timestamp' => $occurredAt->toIso8601String(),
                'url' => route('admin.notifications.queue'),
                'is_unread' => $lastSeenAt ? $occurredAt->gt($lastSeenAt) : true,
                'sort_at' => $occurredAt->timestamp,
            ];
        }

        $adminLogs = AdminActivityLog::query()
            ->with('actorUser:id,name')
            ->latest('created_at')
            ->limit($limit)
            ->get(['id', 'actor_user_id', 'event_type', 'category', 'title', 'message', 'url', 'created_at']);

        foreach ($adminLogs as $adminLog) {
            $occurredAt = $adminLog->created_at ?? now();
            $actorName = $adminLog->actorUser->name ?? 'Admin';
            $message = $adminLog->message;

            if (!str_contains($message, $actorName)) {
                $message = $actorName . ': ' . $message;
            }

            $items[] = [
                'id' => 'admin-log-' . $adminLog->id,
                'category' => $adminLog->category ?: 'admin',
                'title' => $adminLog->title,
                'message' => $message,
                'time_human' => $occurredAt->locale('id')->diffForHumans(),
                'timestamp' => $occurredAt->toIso8601String(),
                'url' => $adminLog->url ?: route('admin.dashboard'),
                'is_unread' => $lastSeenAt ? $occurredAt->gt($lastSeenAt) : true,
                'sort_at' => $occurredAt->timestamp,
            ];
        }

        usort($items, function (array $a, array $b) {
            return ($b['sort_at'] ?? 0) <=> ($a['sort_at'] ?? 0);
        });

        $items = array_slice($items, 0, $limit);

        return array_map(function (array $item) {
            unset($item['sort_at']);
            return $item;
        }, $items);
    }

    /**
     * Calculate unread count based on last seen timestamp.
     */
    private function calculateUnreadCount(?Carbon $lastSeenAt): int
    {
        $newApplicants = Applicant::query();
        $newApplications = Application::query();
        $newQueueSent = NotificationLog::query()
            ->where('status', 'sent')
            ->whereNotNull('scheduled_at')
            ->whereNotNull('sent_at');
        $newAdminLogs = AdminActivityLog::query();

        if ($lastSeenAt) {
            $newApplicants->where('created_at', '>', $lastSeenAt);
            $newApplications->where('created_at', '>', $lastSeenAt);
            $newQueueSent->where('sent_at', '>', $lastSeenAt);
            $newAdminLogs->where('created_at', '>', $lastSeenAt);
        }

        return $newApplicants->count()
            + $newApplications->count()
            + $newQueueSent->count()
            + $newAdminLogs->count();
    }

    /**
     * Read last seen timestamp for current admin.
     */
    private function getLastSeenAt(bool $initializeWhenMissing = false): ?Carbon
    {
        $user = auth()->user();
        if (!$user) {
            return null;
        }

        $lastSeenAt = $user->admin_activity_last_seen_at;
        if ($lastSeenAt instanceof Carbon) {
            return $lastSeenAt;
        }

        if (!$initializeWhenMissing) {
            return null;
        }

        // First-time initialization so unread badge does not jump to old historical events.
        $now = now();
        $user->forceFill([
            'admin_activity_last_seen_at' => $now,
        ])->saveQuietly();

        return $now;
    }

}
