<?php
namespace App\Classes\Modules\Companies\ControllersLogic;

use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyDebtor;
use App\Classes\Modules\Addresses\Services\UpsertsAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Services\UpdatesAddressMetadata;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\UpdatesDocumentReference;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\DataTransferObjects\UpdateCompanyDetailsDTO;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Http\Resources\CompanyResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UpdateCompanyDetailsLogic extends AbstractControllerLogic
{

    /**
     * @return array
     */
    protected function notification():array {
        return [
            'title' => 'Update Company Details',
            'message' => 'You have successfully updated the Company Details'
        ];
    }
    /** @var CanUpdateCompany */
    private $canUpdateCompany;

    /** @var UpdatesCompany */
    private $updatesCompany;

    /** @var FetchesCompany */
    private $fetchesCompany;

    /** @var UpdatesCompanyDebtor */
    private $updatesCompanyDebtor;

    /** @var CanCreateAddress */
    private $canCreateAddress;

    /** @var FetchesDistrict */
    private $fetchesDistrict;

    /** @var UpsertsAddress */
    private $upsertsAddress;

    /** @var UpdatesCompanyEInvoiceInfo */
    private $updatesCompanyEInvoiceInfo;

    /** @var UpdatesAddressMetadata */
    private $updatesAddressMetadata;

    /** @var FetchesDocument */
    private $fetchesDocument;

    /** @var UpdatesDocumentReference */
    private $updatesDocumentReference;

    /** @var CreatesDocument */
    private $createsDocument;

    /** @var CreatesFiles */
    private $createsFile;


    /**
     * UpdateCompanyDetailsLogic constructor.
     * @param CanUpdateCompany $canUpdateCompany
     * @param UpdatesCompany $updatesCompany
     * @param FetchesCompany $fetchesCompany
     * @param UpdatesCompanyDebtor $updatesCompanyDebtor
     * @param CanCreateAddress $canCreateAddress
     * @param FetchesDistrict $fetchesDistrict
     * @param FetchesCompany $fetchesCompany
     * @param UpsertsAddress $upsertsAddress
     * @param UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo;
     * @param UpdatesAddressMetadata $updatesAddressMetadata
     * @param FetchesDocument $fetchesDocument
     * @param UpdatesDocumentReference $updatesDocumentReference
     * @param CreatesDocument $createsDocument
     * @param CreatesFiles $createsFile
     */
    public function __construct(
        CanUpdateCompany $canUpdateCompany,
        UpdatesCompany $updatesCompany,
        FetchesCompany $fetchesCompany,
        UpdatesCompanyDebtor $updatesCompanyDebtor,
        CanCreateAddress $canCreateAddress,
        FetchesDistrict $fetchesDistrict,
        UpsertsAddress $upsertsAddress,
        UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo,
        UpdatesAddressMetadata $updatesAddressMetadata,
        FetchesDocument $fetchesDocument,
        UpdatesDocumentReference $updatesDocumentReference,
        CreatesDocument $createsDocument,
        CreatesFiles $createsFile
    )
    {
        $this->canUpdateCompany = $canUpdateCompany;
        $this->updatesCompany = $updatesCompany;
        $this->fetchesCompany = $fetchesCompany;
        $this->updatesCompanyDebtor = $updatesCompanyDebtor;
        $this->canCreateAddress = $canCreateAddress;
        $this->fetchesDistrict = $fetchesDistrict;
        $this->fetchesCompany = $fetchesCompany;
        $this->upsertsAddress = $upsertsAddress;
        $this->updatesCompanyEInvoiceInfo = $updatesCompanyEInvoiceInfo;
        $this->updatesAddressMetadata = $updatesAddressMetadata;
        $this->fetchesDocument = $fetchesDocument;
        $this->updatesDocumentReference = $updatesDocumentReference;
        $this->createsDocument = $createsDocument;
        $this->createsFile = $createsFile;
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ErrorException
     */
    public function logic(Request $request) : JsonResponse
    {
        $dto = new UpdateCompanyDetailsDTO($request->all());

        $company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
        $object = new CompanyObject($dto->name, $dto->reference, $company->business_type, $dto->type);

        $this->canUpdateCompany->passes($object);

         //Update Name and Debtor
        $company = $this->updatesCompany->execute($company, $object);
        if ($dto->debtor|| $company->first()->debtor !== null) {
            $this->updatesCompanyDebtor->execute($company, $dto->debtor);
        }

        //Update EInvoice Related Info
        if($company->e_invoice){
            $district = $this->fetchesDistrict->execute(['id' => $dto->districtId]);
            $addObj = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $dto->stateId, $district->id, $dto->postCode);
            $this->canCreateAddress->passes($addObj);

            $address = $this->upsertsAddress->execute($company, $addObj, $dto->addressId);
            $query = $this->updatesAddressMetadata->execute($address, false, true);
            $this->updatesCompanyEInvoiceInfo->execute($company, $dto->tin, $dto->msicCode);
        }

        //Update Identification Card / SSM Registration
        if($dto->identificationId){
            $document = $this->fetchesDocument->execute(['id' => $dto->identificationId]);
            $this->updatesDocumentReference->execute($document, $dto->identificationReference);
        }
        else{
            if($dto->identificationReference){
                $pathToFile = base_path('resources/assets/images/ssm_ic_placeholder.png');
                $mimeType = mime_content_type($pathToFile);
                $fileContents = file_get_contents($pathToFile);
                $base64 = base64_encode($fileContents);
                $base64File = "data:$mimeType;base64,$base64";
                $files = [$base64File];

                /** @var Document $document */
                $company = $this->fetchesCompany->execute(['id' => $dto->id]);

                $object = new DocumentObject($company->type === CompanyType::COMPANY_BUSINESS ?
                    DocumentType::SSM_REGISTRATION : DocumentType::IDENTITY_CARD, $files,
                    $dto->identificationReference, ApprovalStatus::PENDING_VERIFICATION, 'identifications');

                $document = $this->createsDocument->execute($company, $object);
                $this->createsFile->execute($document, $object);
            }
        }

        return $this->resourceResponse(new CompanyResource($company));
    }
}

