<?php

namespace App\Services\Meet;

use App\Models\Channel;
use App\Models\ChannelMember;
use App\Models\ChannelMessage;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Support\Str;

class ChannelService
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function create(User $user, Organization $organization, array $data): Channel
    {
        $ownerRef = $user->ownerRef();
        $slug = Str::slug($data['name']);

        $channel = Channel::create([
            'owner_ref' => $ownerRef,
            'organization_id' => $organization->id,
            'branch_id' => $data['branch_id'] ?? null,
            'name' => $data['name'],
            'slug' => $this->uniqueSlug($organization->id, $slug),
            'visibility' => $data['visibility'] ?? 'public',
            'description' => $data['description'] ?? null,
        ]);

        $this->addMember($channel, $ownerRef, 'admin');

        AuditLogger::record($ownerRef, 'channel.created', $organization->id, $ownerRef, Channel::class, $channel->id);

        return $channel;
    }

    public function addMember(Channel $channel, string $userRef, string $role = 'member'): ChannelMember
    {
        return ChannelMember::firstOrCreate(
            ['channel_id' => $channel->id, 'user_ref' => $userRef],
            ['role' => $role],
        );
    }

    public function canAccess(Channel $channel, string $userRef): bool
    {
        if ($channel->visibility === 'public') {
            return true;
        }

        return $channel->members()->where('user_ref', $userRef)->exists();
    }

    public function canPost(Channel $channel, string $userRef): bool
    {
        if ($channel->visibility === 'public') {
            return true;
        }

        return $channel->members()->where('user_ref', $userRef)->exists();
    }

    public function postMessage(Channel $channel, User $user, string $body, ?int $parentId = null): ChannelMessage
    {
        abort_unless($this->canPost($channel, $user->ownerRef()), 403);

        return ChannelMessage::create([
            'owner_ref' => $channel->owner_ref,
            'channel_id' => $channel->id,
            'sender_ref' => $user->ownerRef(),
            'sender_name' => $user->name,
            'body' => trim($body),
            'parent_id' => $parentId,
        ]);
    }

    public function react(ChannelMessage $message, string $emoji, string $userRef): ChannelMessage
    {
        $metadata = $message->metadata ?? [];
        $reactions = $metadata['reactions'] ?? [];
        $reactions[$emoji] = array_values(array_unique(array_merge($reactions[$emoji] ?? [], [$userRef])));
        $metadata['reactions'] = $reactions;
        $message->update(['metadata' => $metadata]);

        return $message->fresh();
    }

    protected function uniqueSlug(int $organizationId, string $base): string
    {
        $slug = $base;
        $i = 1;
        while (Channel::where('organization_id', $organizationId)->where('slug', $slug)->exists()) {
            $slug = $base.'-'.$i++;
        }

        return $slug;
    }
}
