<?php

namespace App\Services\Meet;

use App\Models\Organization;
use App\Models\Room;
use App\Models\User;
use App\Services\Meet\Media\MediaProviderInterface;
use Illuminate\Support\Str;

class RoomService
{
    public function __construct(
        protected MediaProviderInterface $media,
    ) {}

    /**
     * @param  array<string, mixed>  $data
     */
    public function createInstant(User $user, Organization $organization, array $data = []): Room
    {
        return $this->create($user, $organization, array_merge($data, [
            'type' => 'instant',
            'status' => 'scheduled',
            'title' => $data['title'] ?? 'Instant meeting',
        ]));
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function createScheduled(User $user, Organization $organization, array $data): Room
    {
        return $this->create($user, $organization, array_merge($data, [
            'type' => 'scheduled',
            'status' => 'scheduled',
        ]));
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function create(User $user, Organization $organization, array $data): Room
    {
        $ownerRef = $user->ownerRef();
        $settings = array_merge(config('meet.default_settings'), $data['settings'] ?? []);

        $room = Room::create([
            'owner_ref' => $ownerRef,
            'organization_id' => $organization->id,
            'branch_id' => $data['branch_id'] ?? null,
            'host_user_ref' => $data['host_user_ref'] ?? $ownerRef,
            'title' => $data['title'],
            'description' => $data['description'] ?? null,
            'type' => $data['type'] ?? 'instant',
            'status' => $data['status'] ?? 'scheduled',
            'slug' => $data['slug'] ?? null,
            'scheduled_at' => $data['scheduled_at'] ?? now(),
            'duration_minutes' => $data['duration_minutes'] ?? 60,
            'timezone' => $data['timezone'] ?? $organization->timezone,
            'passcode' => isset($data['passcode']) ? (string) $data['passcode'] : null,
            'settings' => $settings,
            'source' => $data['source'] ?? null,
        ]);

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

        app(\App\Services\Integrations\WebhookDispatcher::class)->roomCreated($room);

        return $room;
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function update(Room $room, array $data, ?User $host = null): Room
    {
        $settings = isset($data['settings'])
            ? array_merge($room->settings ?? [], $data['settings'])
            : $room->settings;

        $room->update(array_filter([
            'title' => $data['title'] ?? null,
            'description' => array_key_exists('description', $data) ? $data['description'] : null,
            'scheduled_at' => $data['scheduled_at'] ?? null,
            'duration_minutes' => $data['duration_minutes'] ?? null,
            'timezone' => $data['timezone'] ?? null,
            'passcode' => array_key_exists('passcode', $data) ? ($data['passcode'] !== null ? (string) $data['passcode'] : null) : null,
            'settings' => $settings,
            'source' => $data['source'] ?? null,
            'host_user_ref' => $data['host_user_ref'] ?? null,
        ], fn ($value) => $value !== null));

        AuditLogger::record($room->owner_ref, 'room.updated', $room->organization_id, $room->host_user_ref, Room::class, $room->id);

        if ($host && $room->scheduled_at) {
            app(CalendarService::class)->syncRoomCreated($room->fresh(), $host);
        }

        return $room->fresh();
    }

    public function ensurePersonalRoom(User $user, Organization $organization): Room
    {
        $ownerRef = $user->ownerRef();
        $slug = 'personal-'.Str::slug($organization->slug);

        return Room::firstOrCreate(
            [
                'owner_ref' => $ownerRef,
                'organization_id' => $organization->id,
                'type' => 'personal',
                'slug' => $slug,
            ],
            [
                'host_user_ref' => $ownerRef,
                'title' => $user->name."'s meeting room",
                'status' => 'scheduled',
                'scheduled_at' => now(),
                'timezone' => $organization->timezone,
                'settings' => config('meet.default_settings'),
            ],
        );
    }

    public function cancel(Room $room, string $actorRef, ?User $host = null): Room
    {
        $room->update(['status' => 'cancelled']);
        AuditLogger::record($room->owner_ref, 'room.cancelled', $room->organization_id, $actorRef, Room::class, $room->id);

        if ($host) {
            app(CalendarService::class)->syncRoomCancelled($room, $host);
        }

        app(\App\Services\Integrations\WebhookDispatcher::class)->roomCancelled($room);

        return $room;
    }

    public function mediaRoomName(Room $room, ?string $sessionUuid = null): string
    {
        return 'meet-'.$room->uuid.($sessionUuid ? '-'.$sessionUuid : '');
    }
}
