<?php

namespace App\Http\Resources;

use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Booking;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundServiceCharge;
use App\Classes\ValueObjects\Constants\KVPKey;
use Illuminate\Http\Resources\Json\JsonResource;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class AutocountSalesInvoiceBookingResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        $booking = $this;
        $details = collect();
        $purchaseOrder = $this->transactions->where('type', TransactionType::PURCHASE_ORDER)->first();
        $company = $this->company;

        $lastPaymentTransaction = $this->transactions
            ->where('type', TransactionType::PAYMENT)
            ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
            ->sortByDesc('created_at')
            ->first();

        if(!$lastPaymentTransaction){
            $lastPaymentTransaction = $this->transactions()->payments()->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED])->latest()->first();
        }
        $documentDate = Carbon::parse($lastPaymentTransaction->created_at);

        // if ($documentDate < $this->startDate || $documentDate > $this->endDate) {
        //      return [];
        // }

        if($company->e_invoice === 1){
            $documentDate = $documentDate->copy()->endOfMonth();
        }

        $invoiceTransaction = $this->transactions->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first();

        $currencyId = $this->fix_currency_id;

        $subtotal = 0;
        $displayedSubtotal = 0;
        $totalPayment = 0;
        $averageCurrencyRate = $invoiceTransaction ? $invoiceTransaction->currency_rate : 0;
        $paymentSum = $this->transactions
            ->where('type', TransactionType::PAYMENT)
            ->where('status', ApprovalStatus::COMPLETED)
            ->sum(function ($transaction) {
                return round($transaction->amount, 2);
            });
        if ($paymentSum){
            $averageCurrencyRate = $this->transactions
            ->where('type', TransactionType::PAYMENT)
            ->where('status', ApprovalStatus::COMPLETED)
            ->sum(function ($transaction) {
                return $transaction->currency_rate;
            }) / $this->transactions
            ->where('type', TransactionType::PAYMENT)
            ->where('status', ApprovalStatus::COMPLETED)
            ->count();

            $booking = Booking::where('id', $this->id)->first();
            $refundedAmount = (App()->make(CalculatesBookingRefundAmount::class))->execute($booking, 1);
            $refundedServiceCharge = (App()->make(CalculatesBookingRefundServiceCharge::class))->execute($booking, 1);

            $totalPayment = $paymentSum - $refundedAmount - $refundedServiceCharge;
        }

        $formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y');

        $docNo = '<<New>>';
        $firstItem = true;
        if($invoiceTransaction){
            $invoiceTransactionKVP = $invoiceTransaction->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
            if($invoiceTransactionKVP){
                $docNo = $invoiceTransactionKVP->value;
            }
            else {
                $bookingKVP = $booking->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
                $docNo = $bookingKVP ? $bookingKVP->value :'<<New>>';
            }
        }

        $transactionDetails = $purchaseOrder->transactionDetails;
        foreach ($transactionDetails as $detail) {
            $displayUnitPrice = 0;
            if($averageCurrencyRate && $currencyId){
                $exactUnitPrice = ($currencyId) === 1 ? $detail->price : bcdiv($detail->price, $averageCurrencyRate, 7);
                $displayUnitPrice = round($exactUnitPrice, 2);
                $itemTotal = bcmul($exactUnitPrice, $detail->quantity, 5);
                $displayedItemTotal = round(bcmul($displayUnitPrice, $detail->quantity, 7), 2);
                $displayedSubtotal = bcadd($displayedSubtotal, $displayedItemTotal, 2);
                $subtotal = bcadd($subtotal, $itemTotal, 5);
            }

            $detail = [
                'DocNo' => $firstItem ? $docNo : '',
                'DocDate' => $formattedDocumentDate,
                'DebtorCode' => $company->debtor,
                'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
                'ShipInfo' => $this->marking,
                'AccNo' => '500-0000',
                'DetailDescription' => 'PRODUCT NAME :',
                'FurtherDescription' => $detail->product_name,
                'Classification' => '022',
                'DeptNo' => 'C',
                'Qty' => number_format($detail->quantity, 0),
                'UnitPrice' => $displayUnitPrice ? number_format($displayUnitPrice, 2) : '0',
                'SubmitEinvoice' => $firstItem ? 'T' : '',
                'ConsolidatedEinvoice' => $firstItem ? ($company->e_invoice ? 'F' : 'T') : '',
                'InvoiceStatus' => (string) $this->invoice_status,
            ];
            $details->push($detail);

            if($firstItem) {
                $firstItem = false;
            }
        }

        // Voucherify - Starts
        $voucherRedemption = $lastPaymentTransaction->voucherRedemption;
        if($voucherRedemption){
            $voucherDiscount = $voucherRedemption ? bcmul((string)$voucherRedemption->value, "-1", 2) : "0";
            $voucher = $voucherRedemption->voucher;
            $category = $voucher->campaign ? $voucher->campaign->category : null;
            $detail = [
                'DocNo' => '',
                'DocDate' => $formattedDocumentDate,
                'DebtorCode' => $company->debtor,
                'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
                'ShipInfo' => $this->marking,
                'AccNo' => $category === 'Compensation Voucher' ? '952-0000' : '949-2000',
                'DetailDescription' => 'PRODUCT NAME :',
                'FurtherDescription' => $voucher->code,
                'Classification' => '022',
                'DeptNo' => 'C',
                'Qty' => '1',
                'UnitPrice' => $voucherDiscount ? number_format($voucherDiscount, 2): '0',
                'SubmitEinvoice' => '',
                'ConsolidatedEinvoice' => '',
                'InvoiceStatus' => (string) $this->invoice_status,
            ];
            $details->push($detail);
        }
        // Voucherify - Ends

        // Service Charge - Starts
        $serviceCharge = 0;
        if (!$totalPayment && $invoiceTransaction) {
            $serviceCharge = $invoiceTransaction->service_charge;
        }
        else {
            $serviceCharge = $this->transactions
                ->where('type', TransactionType::PAYMENT)
                ->where('status', ApprovalStatus::COMPLETED)
                ->sum(function ($transaction) {
                    return $transaction->service_charge;
                });
        }

        $detail = [
            'DocNo' => '',
            'DocDate' => $formattedDocumentDate,
            'DebtorCode' => $company->debtor,
            'Ref' => $invoiceTransaction ? $invoiceTransaction->bill_no : '',
            'ShipInfo' => $this->marking,
            'AccNo' => '500-0000',
            'DetailDescription' => 'PRODUCT NAME :',
            'FurtherDescription' => 'Service Charge',
            'Classification' => '022',
            'DeptNo' => 'C',
            'Qty' => '1',
            'UnitPrice' => $serviceCharge ? number_format($serviceCharge, 2) : '0',
            'SubmitEinvoice' => '',
            'ConsolidatedEinvoice' => '',
            'InvoiceStatus' => (string) $this->invoice_status,
        ];
        $details->push($detail);
        // Service Charge - Ends

        // Adjustment - Starts
        if($invoiceTransaction){
            $adjustment = 0;
            $voucherRedemption = $invoiceTransaction->voucherRedemption;
            $voucherDiscount = $voucherRedemption ? bcmul((string)$voucherRedemption->value, "-1", 2) : "0";

            $displayedSubtotal = is_numeric($displayedSubtotal) ? sprintf('%F', $displayedSubtotal) : '0';
            $serviceCharge = is_numeric($serviceCharge) ? sprintf('%F', $serviceCharge) : '0';
            $tax = is_numeric($invoiceTransaction->tax) ? sprintf('%F', $invoiceTransaction->tax) : '0';
            $voucherDiscount = is_numeric($voucherDiscount) ? sprintf('%F', $voucherDiscount) : '0';

            $displayedTotal = bcadd(
                bcadd(
                    bcadd($displayedSubtotal, $serviceCharge, 5),
                    $tax,
                    5
                ),
                $voucherDiscount,
                5
            );

            $expectedTotal = bcadd(bcadd(bcadd($subtotal, $serviceCharge, 5), $invoiceTransaction->tax, 5), $voucherDiscount, 5);
            $adjustment = bcsub($expectedTotal, $displayedTotal, 5);

            if ($totalPayment) {
                $expectedTotal = $totalPayment;
                $adjustment = bcsub($expectedTotal, $displayedTotal, 5);
            }

            $detail = [
                'DocNo' => '',
                'DocDate' => $formattedDocumentDate,
                'DebtorCode' => $company->debtor,
                'Ref' => $invoiceTransaction->bill_no,
                'ShipInfo' => $this->marking,
                'AccNo' => '500-0000',
                'DetailDescription' => 'PRODUCT NAME :',
                'FurtherDescription' => 'Adjustment',
                'Classification' => '022',
                'DeptNo' => 'C',
                'Qty' => '1',
                'UnitPrice' => $adjustment ? number_format($adjustment, 2) : '0',
                'SubmitEinvoice' => '',
                'ConsolidatedEinvoice' => '',
                'InvoiceStatus' => (string) $this->invoice_status,
            ];
            $details->push($detail);
        }
        // Adjustment - Ends

        return AutocountSalesInvoiceBookingDetailsResource::collection(
            collect($details)
        );
    }
}
