<?php

namespace App\Classes\Modules\PerfexCRM\Processors;

use App\Models\Transaction;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Models\PackingList;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class CreatePerfexCRMInvoiceProcessor
{

    /** @var CreatesPerfexCRMInvoice */
    private $createsPerfexCRMInvoice;

    /** @var CreatesPerfexCRMInvoicePayment */
    private $createsPerfexCRMInvoicePayment;

    /** @var ConvertsPerfexCRMLeadToCustomer */
    private $convertsPerfexCRMLeadToCustomer;

    /** @var FetchesPerfexCRMProject */
    private $fetchesPerfexCRMProject;

    /** @var CreatesPerfexCRMCustomerProject */
    private $createsPerfexCRMCustomerProject;

    /**
     * CreatePerfexCRMInvoiceProcessor constructor.
     * @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
     */
    public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice,
    CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
    ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
    FetchesPerfexCRMProject $fetchesPerfexCRMProject,
    CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject)
    {
        $this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
        $this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
        $this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
        $this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
        $this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
    }

    /**
     * @param Transaction $transaction
     * @param bool $isPaid, default: false
     * @return null|object
     * @throws \App\Classes\Exceptions\MalformedRequestException
     */
    public function execute(Transaction $transaction, bool $isPaid = false) {
        $clientId = "";
        $number = $transaction->bill_no;
        $prefix = "INV-";

        //This will remove the prefix if prefix already exist in the string
        if (substr($number, 0, strlen($prefix)) == $prefix) {
            $number = substr($number, strlen($prefix));
        }

        $date = Carbon::parse($transaction->created_at)->format('Y-m-d');
        $dueDate = Carbon::parse($transaction->created_at)->addDays(6)->startOfDay()->format('Y-m-d');
        $currency = 1;
        $subTotal = 0.00;
        $total = 0.00;

        $companyModule = $transaction->owner->owner->companyModule;
        $billingStreet = "";
        $addresses = $companyModule
                    ->addresses()
                    ->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)
                    ->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();

        if ($addresses !== null) {
            $billingStreet = $billingStreet.$addresses->street_one;
            $billingStreet = $billingStreet.$addresses->street_two.',';
            $billingStreet = $billingStreet.$addresses->district()->first()->name.',';
            $billingStreet = $billingStreet.$addresses->postcode;
            $billingStreet = $billingStreet.$addresses->state()->first()->name.',';
            $billingStreet = $billingStreet.$addresses->country()->first()->name;
        }
        else{
            $billingStreet = "[Pending Billing Details by user]";
        }

        $allowedPaymentModes = [];
        $invoiceItems = [];

        $employee = $companyModule->employees()->first();
        $email = $employee->email;

        $result = $this->convertsPerfexCRMLeadToCustomer->execute($email);
        if(isset($result->payload)){
            $clientId = $result->payload['client_id'];
        }

        //get project
        $projectId = ""; //Project only exist in CRM if the customer already made payment
        $projectName = "";
        if($isPaid){
            if($transaction->owner instanceof PackingList){
                $orderReference = $transaction->owner->owner->reference;
                $packingListReference = $transaction->owner->reference;
                $projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
                $result = $this->fetchesPerfexCRMProject->execute($projectName, $clientId);
                if(isset($result->payload)){
                    $project = $result->payload[0];
                    $projectId = $project['id'];
                }
                else{
                    $result = $this->createsPerfexCRMCustomerProject->execute($projectName, PerfexCRMProjectStatus::NOT_STARTED, $clientId);
                    if(isset($result->payload)){  //Here means project creation successful
                        $projectId = $result->payload['project_id'];
                    }
                }
            }

            if($projectId == ""){
                Log::error(json_encode('CreatePerfexCRMInvoiceProcessor debug: '.$projectName));
                Log::error(json_encode($transaction->owner));
            }
        }

        //newitems
        foreach ($transaction->transactionDetails as $key => $transaction_detail){
            $order = $key + 1;
            $description = $transaction_detail->name;
            $quantity = $transaction_detail->quantity;
            $unitPrice = $transaction_detail->price;

            $subTotal = $subTotal + $transaction_detail->amount;

            //string $description, string $longDescription, int $qty, int $rate, int $order, string $unit
            $invoiceSingleItem = new InvoiceSingleItemPerfexCRMObject(
                $description,
                "",
                $quantity,
                $unitPrice,
                $order,
                ""
            );
            array_push($invoiceItems, $invoiceSingleItem);
        }

        // $total = $transaction->amount;
        $total = number_format($transaction->amount, 2,'.','') * 1;

        //This setting is similar to Setup > Leads > Sources, Setup > Leads > Statuses
        //Can be found at Finance > Payment Modes
        array_push($allowedPaymentModes, 1, 2);
        $invoicePerfexCRMObject = new InvoicePerfexCRMObject(
            $clientId,
            $number,
            $date,
            $dueDate,
            $currency,
            $subTotal,
            $total,
            $billingStreet,
            $projectId,
            $allowedPaymentModes,
            $invoiceItems
        );

        $result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject);

        return $result;
    }

}
