<?php

namespace App\Services;

use App\Enums\AppRole;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMember;

class WorkspaceInviteService
{
    /**
     * @return array{ok: true, user_id: int}|array{ok: false, error: string, message: string}
     */
    public function inviteByEmail(
        User $caller,
        Workspace $workspace,
        string $email,
        AppRole $role,
        ?int $assistsInfluencerUserId = null,
        ?int $pairedRestaurantUserId = null,
    ): array {
        $callerMember = WorkspaceMember::query()
            ->where('workspace_id', $workspace->id)
            ->where('user_id', $caller->id)
            ->first();

        $callerRole = $callerMember?->role;
        if (! $callerRole instanceof AppRole) {
            $callerRole = $callerRole !== null ? AppRole::tryFrom((string) $callerRole) : null;
        }

        if ($callerRole === null || ! in_array($callerRole, [AppRole::Influencer, AppRole::Assistant], true)) {
            return [
                'ok' => false,
                'error' => 'forbidden',
                'message' => 'Only influencers and assistants can invite.',
            ];
        }

        if ($role === AppRole::Influencer) {
            return [
                'ok' => false,
                'error' => 'invalid_role',
                'message' => 'Choose assistant, agency, or restaurant.',
            ];
        }

        $email = strtolower(trim($email));
        if ($email === '' || ! str_contains($email, '@') || str_starts_with($email, '@') || str_ends_with($email, '@')) {
            return [
                'ok' => false,
                'error' => 'invalid_email',
                'message' => 'Enter a valid email address.',
            ];
        }

        $invitee = User::query()->whereRaw('lower(email) = ?', [$email])->first();
        if ($invitee === null) {
            return [
                'ok' => false,
                'error' => 'user_not_found',
                'message' => 'No account exists for this email yet. They must sign up first, then you can invite them.',
            ];
        }

        if ((int) $invitee->id === (int) $caller->id) {
            return [
                'ok' => false,
                'error' => 'cannot_invite_self',
                'message' => 'You are already in this workspace.',
            ];
        }

        if (WorkspaceMember::query()->where('workspace_id', $workspace->id)->where('user_id', $invitee->id)->exists()) {
            return [
                'ok' => false,
                'error' => 'already_member',
                'message' => 'This person is already a member.',
            ];
        }

        if ($role === AppRole::Assistant) {
            $ownerId = (int) $workspace->owner_id;
            $assists = $assistsInfluencerUserId ?? $ownerId;
            $influencerMember = WorkspaceMember::query()
                ->where('workspace_id', $workspace->id)
                ->where('user_id', $assists)
                ->where('role', AppRole::Influencer->value)
                ->exists();
            if (! $influencerMember) {
                return [
                    'ok' => false,
                    'error' => 'invalid_assists',
                    'message' => 'Pick an influencer who is already a member of this workspace.',
                ];
            }

            WorkspaceMember::query()->create([
                'workspace_id' => $workspace->id,
                'user_id' => $invitee->id,
                'role' => $role->value,
                'assists_influencer_user_id' => $assists,
                'paired_restaurant_user_id' => null,
            ]);
        } elseif ($role === AppRole::Agency && $pairedRestaurantUserId !== null) {
            $restaurantMember = WorkspaceMember::query()
                ->where('workspace_id', $workspace->id)
                ->where('user_id', $pairedRestaurantUserId)
                ->where('role', AppRole::Restaurant->value)
                ->exists();
            if (! $restaurantMember) {
                return [
                    'ok' => false,
                    'error' => 'invalid_pair',
                    'message' => 'Restaurant contact must be a workspace member with the Restaurant role.',
                ];
            }

            WorkspaceMember::query()->create([
                'workspace_id' => $workspace->id,
                'user_id' => $invitee->id,
                'role' => $role->value,
                'assists_influencer_user_id' => null,
                'paired_restaurant_user_id' => $pairedRestaurantUserId,
            ]);
        } else {
            WorkspaceMember::query()->create([
                'workspace_id' => $workspace->id,
                'user_id' => $invitee->id,
                'role' => $role->value,
                'assists_influencer_user_id' => null,
                'paired_restaurant_user_id' => null,
            ]);
        }

        return ['ok' => true, 'user_id' => (int) $invitee->id];
    }
}
