<?php

namespace App\Livewire\Users;

use App\Domain\Identity\Services\AccountMergeService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Title;
use Livewire\Component;

/**
 * Clearing the duplicate accounts the credential normalisation left behind.
 *
 * This is the prerequisite for ever putting a unique index on users.phone.
 * Until the duplicates are gone, `->first()` on a phone number is an
 * account-selection primitive, which is why AuthService refuses an ambiguous
 * login rather than picking one.
 */
#[Layout('layouts.app')]
#[Title('دمج الحسابات المكررة')]
class DuplicateAccountMerge extends Component
{
    #[Locked]
    public ?int $keepId = null;

    #[Locked]
    public ?int $mergeId = null;

    public function mount(): void
    {
        $this->authorize('users.merge');
    }

    public function choose(int $keepId, int $mergeId): void
    {
        $this->authorize('users.merge');

        // Ids arrive from the browser, so they are re-checked against the
        // academy rather than trusted from the list that rendered them.
        $this->keepId = $this->inScope($keepId)->id;
        $this->mergeId = $this->inScope($mergeId)->id;
    }

    public function cancel(): void
    {
        $this->keepId = null;
        $this->mergeId = null;
    }

    public function merge(AccountMergeService $merger): void
    {
        $this->authorize('users.merge');

        if (! $this->keepId || ! $this->mergeId) {
            return;
        }

        try {
            $merger->merge($this->inScope($this->keepId), $this->inScope($this->mergeId), auth()->user());
            session()->flash('success', __('تم دمج الحسابين'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }

        $this->cancel();
    }

    public function render()
    {
        $academyId = app('current_academy')->id;

        return view('livewire.users.duplicate-account-merge', [
            'groups' => app(AccountMergeService::class)->findDuplicates($academyId),
            'keep' => $this->keepId ? $this->inScope($this->keepId) : null,
            'merge' => $this->mergeId ? $this->inScope($this->mergeId) : null,
        ]);
    }

    private function inScope(int $userId): User
    {
        return User::withoutGlobalScopes()
            ->where('academy_id', app('current_academy')->id)
            ->findOrFail($userId);
    }
}
