<?php

namespace App\Jobs;

use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Intuit\Jobs\AccountingCustomerUpdate;

use App\Models\{Account,ProviderToken};

class AccountingAccountSync implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

	private const LOGKEY = 'JAS';

	private ProviderToken $to;

    /**
     * Create a new job instance.
     *
     * @return void
     */
	public function __construct(ProviderToken $to)
	{
		$this->to = $to;
	}

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
		$api = $this->to->provider->API($this->to);
		$accounts = Account::with(['user'])->get();

		foreach ($api->getCustomers() as $customer) {
			$ao = NULL;

			// See if we are already linked
			if (($x=$this->to->provider->accounts->where('pivot.ref',$customer->id))->count() === 1) {
				$ao = $x->pop();

			// If not, see if our reference matches
			} elseif (($x=$accounts->filter(function($item) use ($customer) { return $item->sid == $customer->ref; }))->count() === 1) {
				$ao = $x->pop();

			// Look based on Name
			} elseif (($x=$accounts->filter(function($item) use ($customer) { return $item->company == $customer->companyname || $item->name == $customer->fullname || $item->user->email == $customer->email; }))->count() === 1) {
				$ao = $x->pop();

			} else {
				// Log not found
				Log::alert(sprintf('%s:Customer not found [%s:%s]',self::LOGKEY,$customer->id,$customer->DisplayName));
				continue;
			}

			$ao->providers()->syncWithoutDetaching([
				$this->to->provider->id => [
					'ref' => $customer->id,
					'synctoken' => $customer->synctoken,
					'created_at'=>Carbon::create($customer->created_at),
					'updated_at'=>Carbon::create($customer->updated_at),
					'site_id'=>$ao->site_id,                         // @todo See if we can have this handled automatically
				],
			]);

			// Check if QB is out of Sync and update it.
			$customer->syncOriginal();
			$customer->PrimaryEmailAddr = (object)['Address'=>$ao->user->email];
			$customer->ResaleNum = $ao->sid;
			$customer->GivenName = $ao->user->firstname;
			$customer->FamilyName = $ao->user->lastname;
			$customer->CompanyName = $ao->name;
			$customer->DisplayName = $ao->name;
			$customer->FullyQualifiedName = $ao->name;
			//$customer->Active = (bool)$ao->active;

			if ($customer->getDirty()) {
				Log::info(sprintf('%s:Customer [%s] (%s:%s) has changed',self::LOGKEY,$ao->sid,$customer->id,$customer->DisplayName),['dirty'=>$customer->getDirty()]);
				$customer->sparse = 'true';

				AccountingCustomerUpdate::dispatch($this->to,$customer);
			}
		}
    }
}