<?php

namespace App\Services\Administrator;

use App\Models\AdminNotificationSubject;
use Illuminate\Support\Facades\DB;

class AdminNotificationSubjectService
{
    public function __construct(
        protected AdminNotificationUserService $userService
    ) {
    }

    public function subjectOptions(): array
    {
        return [
            'academics' => 'Academics',
            'attendance' => 'Attendance',
            'events' => 'Events',
            'finance' => 'Finance',
            'general' => 'General',
            'print_requests' => 'Print Requests',
        ];
    }

    public function alertsData(): array
    {
        $admins = $this->userService->fetchAdminNotificationUsers();
        $subjects = $this->subjectOptions();
        $assignedSubjects = [];
        $tableReady = DB::getSchemaBuilder()->hasTable('admin_notification_subjects');

        if ($tableReady && !empty($admins)) {
            $adminIds = array_map('intval', array_column($admins, 'id'));

            $rows = AdminNotificationSubject::query()
                ->select('id', 'admin_id', 'subject')
                ->whereIn('admin_id', $adminIds)
                ->get();

            foreach ($rows as $row) {
                $adminId = (int) ($row->admin_id ?? 0);
                $subject = (string) ($row->subject ?? '');

                if ($adminId > 0 && $subject !== '') {
                    $assignedSubjects[$adminId][$subject] = true;
                }
            }
        }

        return [
            'admins' => $admins,
            'subjects' => $subjects,
            'assignedSubjects' => $assignedSubjects,
            'tableReady' => $tableReady,
        ];
    }

    public function save(array $posted): array
    {
        if (!DB::getSchemaBuilder()->hasTable('admin_notification_subjects')) {
            return [
                'success' => false,
                'message' => 'Notification subject storage is missing. Run migrations first.',
                'status' => 422,
            ];
        }

        $allowed = array_keys($this->subjectOptions());
        $admins = $this->userService->fetchAdminNotificationUsers();
        $adminIds = array_map('intval', array_column($admins, 'id'));

        if (empty($adminIds)) {
            return [
                'success' => false,
                'message' => 'No admins found to update.',
                'status' => 404,
            ];
        }

        $existing = AdminNotificationSubject::query()
            ->select('id', 'admin_id', 'subject')
            ->whereIn('admin_id', $adminIds)
            ->get();

        $existingMap = [];
        foreach ($existing as $row) {
            $adminId = (int) ($row->admin_id ?? 0);
            $subject = (string) ($row->subject ?? '');
            if ($adminId > 0 && $subject !== '') {
                $existingMap[$adminId][$subject] = (int) ($row->id ?? 0);
            }
        }

        $updates = 0;

        foreach ($adminIds as $adminId) {
            $subjectRaw = $posted[$adminId] ?? [];
            $selected = [];

            if (is_array($subjectRaw)) {
                foreach ($subjectRaw as $key => $value) {
                    $candidate = is_string($key) ? $key : $value;
                    if (!is_string($candidate)) {
                        continue;
                    }
                    $candidate = trim($candidate);
                    if ($candidate !== '' && in_array($candidate, $allowed, true)) {
                        $selected[] = $candidate;
                    }
                }
            }

            $selected = array_values(array_unique($selected));
            $current = array_keys($existingMap[$adminId] ?? []);

            $toDelete = array_values(array_diff($current, $selected));
            $toInsert = array_values(array_diff($selected, $current));

            if (!empty($toDelete)) {
                AdminNotificationSubject::query()
                    ->where('admin_id', $adminId)
                    ->whereIn('subject', $toDelete)
                    ->delete();
                $updates += count($toDelete);
            }

            if (!empty($toInsert)) {
                $batch = [];
                foreach ($toInsert as $subject) {
                    $batch[] = [
                        'admin_id' => $adminId,
                        'subject' => $subject,
                        'created_at' => now(),
                        'updated_at' => now(),
                    ];
                }
                AdminNotificationSubject::insert($batch);
                $updates += count($toInsert);
            }
        }

        return [
            'success' => true,
            'message' => $updates > 0 ? 'Notification subjects updated.' : 'No changes were made.',
            'status' => 200,
        ];
    }
}