<?php

namespace App\Services;

use App\Models\Announcement;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class AnnouncementService
{
    public function __construct(
        protected NotificationService $notificationService
    ) {}

    /**
     * Create/Update an announcement and sync its target audiences.
     */
    public function save(array $data, ?Announcement $announcement = null): Announcement
    {
        return DB::transaction(function () use ($data, $announcement) {
            if (! $announcement) {
                $announcement = new Announcement;
                $announcement->created_by = auth()->id();
            }

            $announcement->fill($data);

            // Handle immediate publication
            if (isset($data['publish_type']) && $data['publish_type'] === 'now') {
                $announcement->publish_at = now();
            }

            // Handle multiple attachments
            if (isset($data['attachments']) && is_array($data['attachments'])) {
                $paths = $announcement->attachments ?? [];
                foreach ($data['attachments'] as $file) {
                    if ($file instanceof \Illuminate\Http\UploadedFile) {
                        $path = $announcement->uploadOne($file, 'announcements/attachments');
                        $paths[] = [
                            'name' => $file->getClientOriginalName(),
                            'path' => $path,
                            'size' => $file->getSize(),
                            'extension' => $file->getClientOriginalExtension(),
                        ];
                    }
                }
                $announcement->attachments = $paths;
            }

            $announcement->save();

            // Sync targets
            if ($data['target_type'] === 'department') {
                $announcement->departments()->sync($data['department_ids'] ?? []);
                $announcement->roles()->detach();
                $announcement->users()->detach();
            } elseif ($data['target_type'] === 'role') {
                $announcement->roles()->sync($data['role_ids'] ?? []);
                $announcement->departments()->detach();
                $announcement->users()->detach();
            } elseif ($data['target_type'] === 'user') {
                $announcement->users()->sync($data['user_ids'] ?? []);
                $announcement->departments()->detach();
                $announcement->roles()->detach();
            } else {
                $announcement->departments()->detach();
                $announcement->roles()->detach();
                $announcement->users()->detach();
            }

            // If it's being published now, trigger notifications
            if ($announcement->publish_at && $announcement->publish_at <= now() && ! $announcement->notified_at) {
                $this->notifyTargets($announcement);
            }

            return $announcement;
        });
    }

    /**
     * Resolve target users and send system notifications.
     */
    public function notifyTargets(Announcement $announcement): void
    {
        $users = $this->getTargetUsers($announcement);

        foreach ($users as $user) {
            $this->notificationService->info(
                userId: $user->id,
                title: __('new_announcement_posted'),
                description: $announcement->title,
                actionUrl: route('employee.announcements.show', ['announcement' => $announcement->id])
            );
        }

        $announcement->update(['notified_at' => now()]);
    }

    /**
     * Get users targeted by the announcement.
     */
    public function getTargetUsers(Announcement $announcement): Collection
    {
        $query = User::query()->where('type', 'employee');

        if ($announcement->target_type === 'department') {
            $departmentIds = $announcement->departments()->pluck('departments.id')->toArray();
            $query->whereHas('employeeProfile', function ($q) use ($departmentIds) {
                $q->whereIn('department_id', $departmentIds);
            });
        } elseif ($announcement->target_type === 'role') {
            $roleIds = $announcement->roles()->pluck('roles.id')->toArray();
            $query->whereHas('roles', function ($q) use ($roleIds) {
                $q->whereIn('roles.id', $roleIds);
            });
        } elseif ($announcement->target_type === 'user') {
            $userIds = $announcement->users()->pluck('users.id')->toArray();
            $query->whereIn('id', $userIds);
        }

        return $query->get();
    }

    /**
     * Mark an announcement as read for a user.
     */
    public function markAsRead(Announcement $announcement, int $userId): void
    {
        $announcement->readByUsers()->syncWithoutDetaching([
            $userId => ['read_at' => now()],
        ]);
    }
}
