<?php

namespace Tests\Services\OrderPackageService\SyncOrderPackageTest;

use App\Commodity;
use App\OracleActAllocationDetails;
use App\OracleBasSKU;
use App\OracleDOCOrderHeader;
use App\Order;
use App\OrderPackage;
use App\Owner;
use App\Services\OracleDOCOrderHeaderService;
use App\Services\OrderPackageService;
use App\Services\OrderService;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Str;
use Tests\TestCase;

class SyncOrderPackageTest extends TestCase
{

    /**
     * @var OrderPackageService $service
     * @var OracleDOCOrderHeaderService $orderHeaderService
     * @var OrderService $orderService
     */
    public $service;
    public $orderService;
    public $orderHeaderService;
    private $data = [];

    public function setUp(): void
    {
        parent::setUp();
        $this->service = app('OrderPackageService');
        $this->orderService = app('OrderService');
        $this->orderHeaderService = app('OracleDocOrderHeaderService');

        $orderHeader = factory(OracleDOCOrderHeader::class)->make(['userdefine1' =>'TEST_OW' ]);
        $order = factory(Order::class)->create(['code'=>$orderHeader['orderno'],'owner_id'=>1]);
        $basSku = factory(OracleBasSKU::class)->make(['customerid' => 'TEST_OW']);
        $OracleActAllocationDetail1 = factory(OracleActAllocationDetails::class)->make(['orderno'=>$orderHeader->orderno,'customerid'=>'TEST_OW','sku'=>$basSku->sku,'checktime'=>now()]);
        $OracleActAllocationDetail2 = factory(OracleActAllocationDetails::class)->make(['orderno'=>$orderHeader->orderno,'customerid'=>'TEST_OW','sku'=>$basSku->sku,'checktime'=>now()]);
        $OracleActAllocationDetail3 = factory(OracleActAllocationDetails::class)->make(['orderno'=>$orderHeader->orderno,'customerid'=>'TEST_OW','sku'=>$basSku->sku,'checktime'=>now()]);
        $OracleActAllocationDetails = collect([$OracleActAllocationDetail1,$OracleActAllocationDetail2,$OracleActAllocationDetail3]);
        $orderHeader->setRelation('actAllocationDetails',$OracleActAllocationDetails);

        $owner = factory(Owner::class)->create(['code'=>'TEST_OW']);
        $commodity = factory(Commodity::class)->create(['sku'=>$basSku['sku'],'owner_id' => $owner]);
        $this->data = [
            'owner' => $owner,
            'commodity' => $commodity,
            'order' => $order,
            'orderHeader' =>  $orderHeader,
            'sku' => $basSku,
            'actAllocationDetails' => $OracleActAllocationDetails,
        ];

    }

    /**
     * @test
     */
    public function syncOrderPackage()
    {
        $orderHeaders = collect([$this->data['orderHeader']]);
        $this->service->syncOrderPackage($orderHeaders);
        $orderPackages = OrderPackage::query()->where('order_id',$this->data['order']['id'])->get();
        $this->assertEquals($orderPackages->count(),count($this->data['orderHeader']->actAllocationDetails));
    }

    /**
     * @test
     */
    public function orderPackageUnnecessary()
    {
        OrderPackage::query()->create(['order_id'=>$this->data['order']['id'],'logistic_number'=>Str::uuid()]);
        OrderPackage::query()->create(['order_id'=>$this->data['order']['id'],'logistic_number'=>Str::uuid()]);
        $orderHeaders = collect([$this->data['orderHeader']]);
        $this->service->syncOrderPackage($orderHeaders);
        $orderPackages = OrderPackage::query()->where('order_id',$this->data['order']['id'])->get();
        $this->assertEquals($orderPackages->count(),count($this->data['orderHeader']->actAllocationDetails));
        foreach($orderPackages as $orderPackage) {
            $this->assertEquals($orderPackage->owner_id,$this->data['order']['owner_id']);
        }

    }

    /**
     * @test
     */
    public function orderPackageSentAtUpdate() {
        $actAllocationDetails = $this->data['orderHeader']->actAllocationDetails;
        foreach ($actAllocationDetails as $actAllocationDetail) {
            $actAllocationDetail->checktime = null;
        }
        $orderHeaders = collect([$this->data['orderHeader']]);
        $this->service->syncOrderPackage($orderHeaders);
        $actAllocationDetails = $this->data['orderHeader']->actAllocationDetails;
        foreach ($actAllocationDetails as $actAllocationDetail) {
            $actAllocationDetail->checktime = '2020-11-01 00:00:00';
        }
        $this->service->syncOrderPackage($orderHeaders);
        $orderPackages = OrderPackage::query()->where('order_id',$this->data['order']['id'])->get();
        $this->assertEquals('2020-11-01 00:00:00', $orderPackages->first()->sent_at);
    }

    /**
     * @test
     */
    public function actAllocationDetail_has_send_at_at_first_time()
    {
        $orderHeaders = collect([$this->data['orderHeader']]);
        $actAllocationDetails = $this->data['orderHeader']->actAllocationDetails;
        foreach ($actAllocationDetails as $actAllocationDetail) {
            $actAllocationDetail->checktime = '2020-11-01 00:00:00';
        }
        $this->service->syncOrderPackage($orderHeaders);
        $orderPackages = OrderPackage::query()->where('order_id',$this->data['order']['id'])->get();
        $this->assertEquals('2020-11-01 00:00:00', $orderPackages->first()->sent_at);
    }

    /**
     * @test
     */
    public function orderPackagesLack()
    {
        $orderHeaders = collect([$this->data['orderHeader']]);
        $this->service->syncOrderPackage($orderHeaders);
        $actAllocationDetails = $this->data['actAllocationDetails']->random(2);
        $this->data['orderHeader']->setRelation('actAllocationDetails', $actAllocationDetails);
        $orderHeaders = collect([$this->data['orderHeader']]);
        $this->service->syncOrderPackage($orderHeaders);
        $orderPackages = OrderPackage::query()->where('order_id',$this->data['order']['id'])->get();
        $this->assertEquals($orderPackages->count(),count($this->data['orderHeader']->actAllocationDetails));
        $this->assertOrderPackage($orderHeaders,$orderPackages);
    }

    public function assertOrderPackage($orderHeaders,$orderPackages)
    {
        foreach ($orderHeaders->first()->actAllocationDetails as $actAllocationDetail) {
            $orderPackage = $orderPackages->where('logistic_number',$actAllocationDetail->picktotraceid)->first();
            $this->assertNotEmpty($orderPackage);
        }
    }

    protected function tearDown(): void
    {
        $this->data['owner']->delete();
        $this->data['commodity']->delete();
        $this->data['order']->delete();

        parent::tearDown(); // TODO: Change the autogenerated stub
    }


}
