<?php

namespace App\Services;

use App\Models\Announcement;
use App\Models\User;
use App\Models\SchoolClass;
use App\Models\Batch;

class AnnouncementService
{
    public function getAnnouncementsForUser(User $user)
    {
        $now = now();
        
        $query = Announcement::where('active', true)
            ->whereNull('deleted_at')
            ->where(function ($q) use ($now) {
                $q->where('display_from', '<=', $now)->orWhereNull('display_from');
            })
            ->where(function ($q) use ($now) {
                $q->where('display_until', '>=', $now)->orWhereNull('display_until');
            });

        $query->where(function ($q) use ($user) {
            // All users announcements
            $q->where('target_type', 'all');

            if ($user->isStudent()) {
                // All students announcements
                $q->orWhere('target_type', 'all_students');
                
                // Student-specific announcements
                $q->orWhere(function ($subQ) use ($user) {
                    $subQ->where('target_type', 'student')->where('target_id', $user->id);
                });
                
                // Batch announcements
                if ($user->batch_id) {
                    $q->orWhere(function ($subQ) use ($user) {
                        $subQ->where('target_type', 'batch')->where('target_id', $user->batch_id);
                    });
                }
                
                // Class announcements
                if ($user->batch?->school_class_id) {
                    $q->orWhere(function ($subQ) use ($user) {
                        $subQ->where('target_type', 'class')->where('target_id', $user->batch->school_class_id);
                    });
                }
            } else {
                // All staff announcements
                $q->orWhere('target_type', 'all_staff');
                
                // Staff-specific announcements
                $q->orWhere(function ($subQ) use ($user) {
                    $subQ->where('target_type', 'staff')->where('target_id', $user->id);
                });
            }
        });

        // No server-side dismissal filtering - handled by client-side sessionStorage

        return $query->orderBy('created_at', 'desc')->get();
    }

    public function dismissAnnouncement(User $user, Announcement $announcement)
    {
        $dismissedIds = session('dismissed_announcements', []);
        if (!in_array($announcement->id, $dismissedIds)) {
            $dismissedIds[] = $announcement->id;
            session(['dismissed_announcements' => $dismissedIds]);
        }
        return true;
    }

    public function createAnnouncement(array $data)
    {
        return Announcement::create($data);
    }

    public function updateAnnouncement(Announcement $announcement, array $data)
    {
        // Remove created_by from update data to prevent overwriting
        unset($data['created_by']);
        return $announcement->update($data);
    }

    public function deleteAnnouncement(Announcement $announcement)
    {
        return $announcement->delete();
    }

    public function getAllAnnouncements()
    {
        return Announcement::with('creator')->orderBy('created_at', 'desc')->paginate(15);
    }

    public function getTargetOptions()
    {
        return [
            'all' => 'All Users',
            'all_students' => 'All Students',
            'all_staff' => 'All Staff',
            'student' => 'Specific Student',
            'staff' => 'Specific Staff',
            'class' => 'Specific Class',
            'batch' => 'Specific Batch',
        ];
    }

    public function getStudents()
    {
        return User::whereDoesntHave('roles')->orderBy('firstname')->get();
    }

    public function getStaff()
    {
        return User::whereHas('roles')->orderBy('firstname')->get();
    }

    public function getClasses()
    {
        return SchoolClass::orderBy('order')->get();
    }

    public function getBatches()
    {
        return Batch::with('schoolClass')->orderBy('name')->get();
    }
}