<?php

namespace App\Http\Livewire;

use App\Models\Account;
use App\Models\Organization;
use App\Traits\LocationTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Storage;
use Livewire\Component;

class ToAccountOrganizationOnly extends Component
{
    use LocationTrait;

    public $label;
    public $search;
    public $searchResults = [];
    public $showDropdown = false;
    public $toAccountId;
    public $toAccountName;
    public $toHolderName;
    public $toHolderFullName;
    public $toHolderLocation;
    public $toHolderType;
    public $toHolderPhoto;

    protected $listeners = ['resetForm', 'resetToAccount' => 'resetForm', 'removeSelectedAccount'];

    public function mount($toAccountId = null)
    {
        if ($toAccountId && !($toAccountId instanceof \Illuminate\Support\Collection)) {
            $this->updatedSearch();
            $this->toAccountSelected($toAccountId);
        }
    }

    public function checkValidation()
    {
        $this->dispatch('toAccountId', $this->toAccountId);
    }

    public function resetForm()
    {
        $this->reset([
            'search',
            'searchResults',
            'showDropdown',
            'toAccountId',
            'toAccountName',
            'toHolderName',
            'toHolderFullName',
            'toHolderLocation',
            'toHolderType',
            'toHolderPhoto',
        ]);
    }

    public function toAccountSelected($toAccountId)
    {
        $this->toAccountId = $toAccountId;
        $toAccountDetails = collect($this->searchResults)->firstWhere('accountId', $toAccountId);

        if ($toAccountDetails) {
            $this->toAccountName = $toAccountDetails['accountName'];
            $this->toHolderName = $toAccountDetails['holderName'];
            $this->toHolderFullName = $toAccountDetails['holderFullName'];
            $this->toHolderLocation = $toAccountDetails['holderLocation'];
            $this->toHolderType = $toAccountDetails['holderType'];
            $this->toHolderPhoto = $toAccountDetails['holderPhoto'];
            $this->dispatch('toAccountDetails', $toAccountDetails);
            $this->dispatch('toAccountId', $this->toAccountId);
        } else {
            $this->toAccountName = null;
            $this->toHolderName = null;
            $this->toHolderFullName = null;
            $this->toHolderLocation = null;
            $this->toHolderType = null;
            $this->toHolderPhoto = null;
            $this->dispatch('toAccountDetails', null);
            $this->dispatch('toAccountId', null);
        }
        $this->search = '';
    }

    /**
     * updatedSearch: Search query for Organization Accounts only
     *
     * @return void
     */
    public function updatedSearch()
    {
        $search = $this->search;

        if ($search) {
            $this->showDropdown = true;
            $accounts = Account::with('accountable')
                ->where(function ($query) use ($search) {
                    $query->where('name', 'like', '%' . $search . '%')
                        ->orWhereHas('accountable', function (Builder $query) use ($search) {
                            $query->where('name', 'like', '%' . $search . '%')
                                ->orWhere('full_name', 'like', '%' . $search . '%')
                                ->orWhere('email', 'like', '%' . $search . '%');
                        });
                })
                // Filter only for Organization accounts
                ->where('accountable_type', Organization::class)
                // Exclude accounts that are set to inactive or have been removed
                ->active()
                ->notRemoved()
                // Exclude accountables that are set to inactive or have been removed
                ->whereHas('accountable', function (Builder $query) {
                    $query->active()->notRemoved();
                })
                ->get();
        } else {
            // No search, because a toAccountId is already known
            $accounts = Account::with('accountable')
                ->where('id', $this->toAccountId)
                ->where('accountable_type', Organization::class)
                ->where(function ($query) {
                    $query->whereNull('inactive_at')
                        ->orWhere('inactive_at', '>', now());
                })
                ->get();
        }

        $mappedAccounts = $accounts
            ->map(function ($account) {
                return [
                    'accountId' => $account->id,
                    'accountName' => $account->name,
                    'holderId' => $account->accountable->id,
                    'holderName' => $account->accountable->name,
                    'holderFullName' => $account->accountable->full_name,
                    'holderLocation' => $account->accountable->getLocationFirst()['name_short'],
                    'holderType' => $account->accountable_type,
                    'holderPhoto' => url(Storage::url($account->accountable->profile_photo_path)),
                ];
            })
            // Sort the collection by 'holderName'
            ->sortBy(function ($account) {
                return strtolower($account['holderName']);
            })
            // Re-index the collection keys
            ->values();

        $response = $mappedAccounts->take(6);

        $this->searchResults = $response;
    }

    public function removeSelectedAccount()
    {
        $this->toAccountId = null;
        $this->toHolderName = null;
        $this->dispatch('toAccountId', null);
        $this->dispatch('toAccountDetails', null);
    }

    public function render()
    {
        $this->updatedSearch($this->search);
        return view('livewire.to-account-organization-only');
    }
}
