<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Group;
use App\Models\GroupRecruitmentProfile;
use App\Models\User;

class GroupRecruitmentService
{
    public function __construct(
        private readonly GroupHistoryService $history,
        private readonly NotificationService $notifications,
    ) {
    }

    public function upsert(Group $group, array $attributes, User $actor): GroupRecruitmentProfile
    {
        $profile = GroupRecruitmentProfile::query()->firstOrNew([
            'group_id' => $group->id,
        ]);

        $before = $profile->exists ? $profile->only([
            'is_recruiting',
            'headline',
            'description',
            'roles_json',
            'skills_json',
            'contact_mode',
            'visibility',
        ]) : null;

        $profile->fill([
            'is_recruiting' => (bool) ($attributes['is_recruiting'] ?? false),
            'headline' => $attributes['headline'] ?? null,
            'description' => $attributes['description'] ?? null,
            'roles_json' => $this->normalizeList($attributes['roles_json'] ?? []),
            'skills_json' => $this->normalizeList($attributes['skills_json'] ?? []),
            'contact_mode' => $attributes['contact_mode'] ?? null,
            'visibility' => (string) ($attributes['visibility'] ?? 'public'),
        ])->save();

        if ($profile->is_recruiting && $profile->visibility === 'public') {
            foreach ($group->follows()->with('user.profile')->get() as $follow) {
                if ($follow->user) {
                    $this->notifications->notifyGroupRecruitmentUpdated($follow->user, $actor, $group, $profile);
                }
            }
        }

        $this->history->record(
            $group,
            $actor,
            'recruitment_updated',
            $profile->is_recruiting ? 'Enabled or updated recruitment profile.' : 'Disabled recruitment profile.',
            'group_recruitment_profile',
            (int) $profile->id,
            $before,
            $profile->only([
                'is_recruiting',
                'headline',
                'description',
                'roles_json',
                'skills_json',
                'contact_mode',
                'visibility',
            ]),
        );

        return $profile->fresh();
    }

    public function payloadForGroup(Group $group): ?array
    {
        $profile = $group->relationLoaded('recruitmentProfile')
            ? $group->recruitmentProfile
            : $group->recruitmentProfile()->first();

        if (! $profile) {
            return null;
        }

        return [
            'id' => (int) $profile->id,
            'is_recruiting' => (bool) $profile->is_recruiting,
            'headline' => $profile->headline,
            'description' => $profile->description,
            'roles' => array_values(array_filter($profile->roles_json ?? [])),
            'skills' => array_values(array_filter($profile->skills_json ?? [])),
            'contact_mode' => $profile->contact_mode,
            'visibility' => $profile->visibility,
            'updated_at' => $profile->updated_at?->toISOString(),
            'roles_options' => config('groups.recruitment.roles', []),
            'skills_options' => config('groups.recruitment.skills', []),
        ];
    }

    private function normalizeList(array $items): array
    {
        return collect($items)
            ->map(fn ($item): string => trim((string) $item))
            ->filter()
            ->unique()
            ->values()
            ->all();
    }
}