<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use App\Models\Announcement;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AnnouncementController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = Announcement::query();

        if ($request->filled('search')) {
            $s = $request->input('search');
            $query->where('title', 'like', "%{$s}%");
        }

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

        $items = $query->orderByDesc('created_at')->paginate(15);

        return response()->json($items);
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'title'        => 'required|string|max:255',
            'body'         => 'required|string',
            'type'         => 'required|in:info,warning,success,danger',
            'audience'     => 'required|in:all,free,starter,pro,enterprise',
            'is_active'    => 'boolean',
            'published_at' => 'nullable|date',
            'expires_at'   => 'nullable|date|after:published_at',
        ]);

        $validated['published_at'] = $validated['published_at'] ?? now();

        $announcement = Announcement::create($validated);

        if ($announcement->is_active) {
            $this->dispatchNotifications($announcement);
        }

        return response()->json(['message' => 'Announcement created.', 'data' => $announcement], 201);
    }

    public function update(Request $request, Announcement $announcement): JsonResponse
    {
        $validated = $request->validate([
            'title'        => 'sometimes|string|max:255',
            'body'         => 'sometimes|string',
            'type'         => 'sometimes|in:info,warning,success,danger',
            'audience'     => 'sometimes|in:all,free,starter,pro,enterprise',
            'is_active'    => 'boolean',
            'published_at' => 'nullable|date',
            'expires_at'   => 'nullable|date',
        ]);

        $announcement->update($validated);

        return response()->json(['message' => 'Announcement updated.', 'data' => $announcement]);
    }

    public function destroy(Announcement $announcement): JsonResponse
    {
        $announcement->delete();
        return response()->json(['message' => 'Announcement deleted.']);
    }

    public function toggleStatus(Announcement $announcement): JsonResponse
    {
        $newStatus = !$announcement->is_active;
        $announcement->update(['is_active' => $newStatus]);

        // Dispatch notifications to relevant org users when going live
        if ($newStatus) {
            $this->dispatchNotifications($announcement);
        }

        return response()->json(['message' => 'Status toggled.', 'is_active' => $announcement->is_active]);
    }

    /**
     * Insert a notification row into the `notifications` table for every active
     * user in every organisation that matches the announcement's audience filter.
     * Runs as a single bulk INSERT (chunked at 500 rows) to stay efficient even
     * with large user bases.
     */
    private function dispatchNotifications(Announcement $announcement): void
    {
        $orgQuery = Organization::where('is_active', true);

        if ($announcement->audience !== 'all') {
            if ($announcement->audience === 'free') {
                // "free" audience = orgs with no active/trial paid subscription
                $orgQuery->where(function ($q) {
                    $q->whereDoesntHave('subscription', fn ($s) => $s->whereIn('status', ['active', 'trial']))
                      ->orWhereHas('subscription', fn ($s) => $s->where('plan', 'free')->whereIn('status', ['active', 'trial']));
                });
            } else {
                $orgQuery->whereHas('subscription', fn ($s) => $s
                    ->where('plan', $announcement->audience)
                    ->whereIn('status', ['active', 'trial'])
                );
            }
        }

        $orgIds = $orgQuery->pluck('id');

        if ($orgIds->isEmpty()) {
            return;
        }

        $users = User::whereIn('organization_id', $orgIds)
            ->where('is_active', true)
            ->select('id', 'organization_id')
            ->get();

        if ($users->isEmpty()) {
            return;
        }

        $now  = now();
        $data = json_encode([
            'announcement_id'   => $announcement->id,
            'announcement_type' => $announcement->type,
        ]);

        $rows = $users->map(fn ($u) => [
            'organization_id' => $u->organization_id,
            'branch_id'       => null,
            'user_id'         => $u->id,
            'actor_id'        => null,
            'type'            => 'announcement',
            'title'           => $announcement->title,
            'body'            => $announcement->body,
            'data'            => $data,
            'read_at'         => null,
            'created_at'      => $now,
            'updated_at'      => $now,
        ])->all();

        foreach (array_chunk($rows, 500) as $chunk) {
            DB::table('notifications')->insert($chunk);
        }
    }
}
