<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Validator;
use JetBrains\PhpStorm\ArrayShape;
use Mtc\MercuryDataModels\Tenant;
use Mtc\MercuryDataModels\User;
use Stancl\Tenancy\Database\Concerns\CentralConnection;

class ResendInviteRequest extends FormRequest
{
    use CentralConnection;

    private ?User $targetUser = null;
    private ?Tenant $site = null;
    private ?string $userRole = null;

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return Auth::check();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    #[ArrayShape(['userId' => "string[]"])] public function rules()
    {
        $global = $this->getConnectionName();
        return [
            'userId' => [
                'required',
                'integer',
                "exists:$global.users,id"
            ],
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param Validator $validator
     * @return void
     */
    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator) {
            if (!$this->userBelongsToTenant()) {
                $validator->errors()->add('userId', 'This user is not assigned to this site.');
                return;
            }

            if ($this->userHasLoggedIn()) {
                $validator->errors()->add('userId', 'Cannot resend invite to a user who has already logged in.');
            }
        });
    }

    /**
     * Check if user belongs to this tenant
     *
     * @return bool
     */
    private function userBelongsToTenant(): bool
    {
        $userId = $this->input('userId');
        if (!$userId) {
            return false;
        }

        return Tenant::query()
            ->where('id', tenant('id'))
            ->whereHas('users', function ($query) use ($userId) {
                $query->where('users.id', $userId);
            })
            ->exists();
    }

    /**
     * Check if user has already logged in
     *
     * @return bool
     */
    private function userHasLoggedIn(): bool
    {
        $user = $this->getTargetUser();
        return $user->last_login_at !== null;
    }

    /**
     * Get the user to resend invite to
     *
     * @return User
     */
    public function getTargetUser(): User
    {
        if (!$this->targetUser) {
            $this->targetUser = User::query()->findOrFail($this->input('userId'));
        }

        return $this->targetUser;
    }

    /**
     * Get the current site
     *
     * @return Tenant
     */
    public function getSite(): Tenant
    {
        if (!$this->site) {
            $this->site = Tenant::query()->findOrFail(tenant('id'));
        }

        return $this->site;
    }

    /**
     * Get the user's role on the current site
     *
     * @return string
     */
    public function getUserRole(): string
    {
        if ($this->userRole === null) {
            $this->userRole = $this->getTargetUser()->tenants()
                ->where('tenant_id', tenant('id'))
                ->first()
                ->pivot
                ->role ?? '';
        }

        return $this->userRole;
    }
}
