<?php

namespace Tests\Services\OrderService;

use App\Batch;
use App\Logistic;
use App\OracleBasCode;
use App\OracleDOCOrderHeader;
use App\Order;
use App\Owner;
use App\Services\OrderService;
use App\Shop;
use App\Warehouse;
use Tests\TestCase;

class SyncOrderByWMSOrderHeadersTest extends TestCase
{

    /** @var OrderService $service */
    private $service;
    private $data = [];

    protected function setUp(): void
    {
        parent::setUp(); // TODO: Change the autogenerated stub
        $this->service = app('OrderService');
        $owners = factory(Owner::class)->times(10)->create();
        $logistics = factory(Logistic::class)->times(20)->create();
        $wareHouses = factory(Warehouse::class)->times(3)->create();
        $shops = collect();
        foreach ($owners as $owner) {
            $shops = $shops->concat(factory(Shop::class)->times(rand(3,5))->create(['owner_id'=>$owner->id]));
        }
        $batches = factory(Batch::class)->times(10)->create();
        $orderHeaders = collect();
        foreach ($owners as $owner) {
            $count = rand(1,10);
            for ($i=0;$i<=$count;$i++) {
                $shop = $shops->where('owner_id',$owner->id)->random();
                $warehouse = $wareHouses->random();
                $logistic = $logistics->random();
                $batch = $batches->random();
                $orderHeader = factory(OracleDOCOrderHeader::class)->make([
                    'warehouseid'=>$warehouse->code,
                    'waveno'=>$batch->code,
                    'customerid'=>$owner->code,
                    'userdefine1'=>$logistic->code,
                    'issuepartyname' => $shop->name,
                ]);
                $oracleBASCode = factory(OracleBasCode::class)->make();
                $orderType = factory(OracleBasCode::class)->make();
                $orderHeader->setRelation('oracleBASCode',$oracleBASCode);
                $orderHeader->setRelation('orderType',$orderType);
                $orderHeaders = $orderHeaders->push($orderHeader);
            }
        }
        $this->data = [
            'warehouses' => $wareHouses,
            'batches' => $batches,
            'owners' => $owners,
            'logistics' => $logistics,
            'shops' => $shops,
            'orderHeaders' => $orderHeaders
        ];
    }

    /**
     * @test
     */
    public function syncOrderByWMSOrderHeaders()
    {
        $this->service->syncOrderByWMSOrderHeaders($this->data['orderHeaders']);
        $orders = Order::query()->whereIn('code',data_get($this->data['orderHeaders'],'*.orderno'))->get();
        $this->data['orders'] = $orders;
        $this->assertEquals(count($orders),count($this->data['orderHeaders']));
        $this->assertOrderHeadersAndOrder($this->data['orderHeaders'],$orders);

    }

    /**
     * @test 订单已存在
     */
    public function orderExisting()
    {

        $this->service->syncOrderByWMSOrderHeaders($this->data['orderHeaders']);
        $this->service->syncOrderByWMSOrderHeaders($this->data['orderHeaders']);
        $orders = Order::query()->whereIn('code',data_get($this->data['orderHeaders'],'*.orderno'))->get();
        $this->data['orders'] = $orders;
        $this->assertEquals(count($orders),count($this->data['orderHeaders']));
        $this->assertOrderHeadersAndOrder($this->data['orderHeaders'],$orders);
    }

    /**
     * @test 订单部分存在
     */
    public function orderPortionExisting()
    {
        $orderHeaders = $this->data['orderHeaders']->random(30);
        $this->service->syncOrderByWMSOrderHeaders($orderHeaders);
        $this->service->syncOrderByWMSOrderHeaders($this->data['orderHeaders']);
        $orders = Order::query()->whereIn('code',data_get($this->data['orderHeaders'],'*.orderno'))->get();
        $this->data['orders'] = $orders;
        $this->assertEquals(count($orders),count($this->data['orderHeaders']));
        $this->assertOrderHeadersAndOrder($this->data['orderHeaders'],$orders);
    }

    /**
     * @test 订单部分在且有修改
     */
    public function orderPortingExistingAndModified()
    {
        $orderHeaders = $this->data['orderHeaders']->random(20);
        foreach ($orderHeaders as $orderHeader) {
            $owner = $this->data['owners']->random();
            $shop = $this->data['shops']->where('owner_id',$owner->id)->random();
            $warehouse = $this->data['warehouses']->random();
            $logistic = $this->data['logistics']->random();
            $batch = $this->data['batches']->random();
            $orderHeader['warehouseid']=$warehouse->code;
            $orderHeader['waveno']=$batch->code;
            $orderHeader['customerid']=$owner->code;
            $orderHeader['userdefine1']=$logistic->code;
            $orderHeader['issuepartyname'] = $shop->name;
        }
        $this->service->syncOrderByWMSOrderHeaders($orderHeaders);
        $this->service->syncOrderByWMSOrderHeaders($this->data['orderHeaders']);
        $orders = Order::query()->whereIn('code',data_get($this->data['orderHeaders'],'*.orderno'))->get();
        $this->data['orders'] = $orders;
        $this->assertEquals(count($orders),count($this->data['orderHeaders']));
        $this->assertOrderHeadersAndOrder($this->data['orderHeaders'],$orders);
    }

    public function assertOrderHeadersAndOrder($orderHeaders,$orders){
        foreach ($orderHeaders as $orderHeader) {
            $warehouse = Warehouse::query()->where('code',$orderHeader['warehouseid'])->first();
            $batch = Batch::query()->where('code',$orderHeader['waveno'])->first();
            $owner = Owner::query()->where('code',$orderHeader['customerid'])->first();
            $logistic = Logistic::query()->where('code',$orderHeader['userdefine1'])->first();
            $shop = Shop::query()->where('name',$orderHeader['issuepartyname'])->first();
            $order = $orders->where('code',$orderHeader['orderno'])->first();
            $this->assertNotEmpty($order);
            $this->assertEquals($order->warehouse_id, $warehouse->id);
            $this->assertEquals($order->batch_id,$batch->id);
            $this->assertEquals($order->owner_id,$owner->id);
            $this->assertEquals($order->logistic_id,$logistic->id);
            $this->assertEquals($order->shop_id,$shop->id);
            $this->assertEquals($order->wms_status,$orderHeader->oracleBASCode->codename_c ?? '');
            $this->assertEquals($order->order_type,$orderHeader->orderType->codename_c ?? '');
        }
    }


    protected function tearDown(): void
    {
        Warehouse::destroy(data_get($this->data['warehouses'],'*.id'));
        Batch::destroy(data_get($this->data['batches'],'*.id'));
        Owner::destroy(data_get($this->data['owners'],'*.id'));
        Logistic::destroy(data_get($this->data['logistics'],'*.id'));
        Shop::destroy(data_get($this->data['shops'],'*.id'));
        Order::destroy(data_get($this->data['orders'],'*.id'));
        parent::tearDown(); // TODO: Change the autogenerated stub
    }
}
