<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Support\Facades\Request;

class Order extends BaseModel
{
    public static function createOrderNumber()
    {
        $times = 10;
        $str = substr(Carbon::now()->format('Ymdhis'), 2);
        do {
            $str = $str . mt_rand(10000, 99999);
            $res = self::where('order_number', $str)->first();
            if(!$res) break;
            $times = $times - 1;
        } while($times);

        return $str;
    }

    public function user()
    {
        return $this->belongsTo('App\Models\User', 'user_id');
    }

    public function project()
    {
        return $this->belongsTo('App\Models\Project', 'project_id');
    }

    public function workPoint()
    {
        return $this->belongsTo('App\Models\WorkPoint', 'work_point_id');
    }

    public function devices()
    {
        return $this->belongsToMany('App\Models\Device', 'order_devices', 'order_id', 'device_id')->withPivot('name', 'quantity', 'price', 'start_date', 'end_date', 'id');
    }

    public function innerDevices()
    {
        return $this->belongsToMany('App\Models\InnerDevice', 'order_devices', 'order_id', 'inner_device_id')->withPivot('id', 'start_date', 'end_date');
    }

    public function getOrderStatus(Project $project, $user, $is_draft)
    {
        if($is_draft) {
            return Option::get('orders', 'status', 'checking');
        }
        if($project->isTopLevel($user)) {
            return Option::get('orders', 'status', 'pass');
        }
        return Option::get('orders', 'status', 'checking');
    }

    public function getStatusName()
    {
        $option = Option::find($this['status']);
        if(!$option) return '';
        if($option['key'] == 'checking') return $option['name'];
        else if(in_array($option['key'], ['checked', 'reject'])) {
            $project_role = ProjectRole::find($this['last_project_role_id']);
            return $project_role ? $project_role->name . ' - ' . $option['name'] : $option['name'];
        } else if($option['key'] == 'pass') {
            if($this['is_change'] == 1) return '管理员 - 已修订';
            return '已完成';
        }
        return $option ? $option['name'] : '';
    }

    public function updateMoney()
    {
        $total = 0;
        $devices = OrderDevice::where('order_id', '=', $this['id'])->get();
        foreach($devices as $device) {
            $total = $total + ($device['price'] * (int)$device['quantity']);
        }
        $this->update(['money' => $total]);
    }

    public function formatOrder($item)
    {
        if($item->type == 1) {
            $item->devices = OrderDevice::where('order_id', $item->id)->get();
            foreach($item->devices as $device) {
                $device->device = Device::find($device->device_id);
                $device->device_name = DeviceName::find($device->device_name_id);
                $device->spec = Spec::find($device->spec_id);
                $device->rent_type = RentType::find($device->rent_type_id);
            }
        } else if($item->type == 2) {
            $item->devices = $item->innerDevices;
        }
        $item->user_name = $item->user ? $item->user->name : '';
        $item->work_point_name = $item->workPoint ? $item->workPoint->name : '';

        $option = Option::find($item->status);
        $item->status = $item->getStatusName();
        $item->status_key = $option ? $option['key'] : '';
        $item->color = $option ? $option['color'] : '';
        $item->date_time = substr($item->created_at, 0, 16);
    }

    public function backInnerDevices($devices)
    {
        $back_devices = [];
        $back_device_ids = [];
        foreach ($devices as $device) {
            if(isset($device['checked']) && $device['checked']) {
                array_push($back_devices, $device);
                array_push($back_device_ids, $device['id']);
            }
        }

        $new_order = null;

        if(count($back_devices) < count($devices)) {
            $status = Option::get('orders', 'status', 'pass', 'id');
            $last_role = ProjectRole::getLastRole($this);
            $level = $last_role ? $last_role['level'] : '';
            $new_order = Order::create([
                'work_point_id' => $this['work_point_id'],
                'remark' => $this['remark'],
                'money' => $this['money'],
                'is_draft' => $this['is_draft'],
                'status' => $status,
                'order_number' => self::createOrderNumber(),
                'project_id' => $this['project_id'],
                'user_id' => $this['user_id'],
                'project_role_id' => $this['project_role_id'],
                'level' => $level,
                'last_project_role_id' => $this['last_project_role_id'],
                'last_user_id' => $this['last_user_id'],
                'is_change' => $this['is_change'],
                'type' => $this['type']
            ]);
            OrderDevice::where('order_id', $this['id'])->whereIn('inner_device_id', $back_device_ids)->update(['order_id' => $new_order->id, 'end_date' => Carbon::now()->toDateString()]);
        }
        $free_id = Option::get('inner_devices', 'status', 'free');
        InnerDevice::whereIn('id', $back_device_ids)->update([
            'status' => $free_id,
            'start_date' => null,
            'end_date' => null,
            'work_point_id' => ''
        ]);
        return $new_order;
    }

    public function updateOrderDevices($devices)
    {
        OrderDevice::where('order_id', '=', $this['id'])->delete();
        if($this['type'] == 1) {
            $total = 0;
            foreach($devices as $device) {
                $price = $this->transMoney($device['price']);
                $data = $this->getNameSpecRent($device);
                OrderDevice::create(array_merge([
                    'order_id' => $this['id'],
                    'project_id' => $this['project_id'],
                    'quantity' => $device['quantity'],
                    'price' => $price,
                    'start_date' => $device['start_date'],
                    'end_date' => $device['end_date']
                ], $data));
                $total = $total + ($price * (int)$device['quantity']);
            }
            $this->update(['money' => $total]);
        } else {
            $using_id = Option::get('inner_devices', 'status', 'using');
            foreach($devices as $device) {
                OrderDevice::create([
                    'name' => $device['name'],
                    'order_id' => $this['id'],
                    'project_id' => $this['project_id'],
                    'user_id' => $this['user_id'],
                    'inner_device_id' => $device['id'],
                    'start_date' => $device['start_date'],
                    'end_date' => $device['end_date']
                ]);
                if($device['id']) {
                    InnerDevice::find($device['id'])->update([
                        'project_id' => $this['project_id'],
                        'status' => $using_id,
                        'start_date' => $device['start_date'],
                        'end_date' => $device['end_date'],
                        'work_point_id' => $this['work_point_id']
                    ]);
                }
            }
        }
    }

    public function getNameSpecRent($data)
    {
        $device = Device::find($data['type_id']);

        $rent_type = RentType::firstOrCreate([
            'name' => $data['rent']
        ]);
        if(!$device) return [
            'device_id' => '',
            'device_name_id' => '',
            'spec_id' => '',
            'rent_type_id' => $rent_type->id
        ];
        $device_name = DeviceName::firstOrCreate([
            'device_id' => $device->id,
            'name' => $data['name']
        ]);
        $spec = Spec::firstOrCreate([
            'device_id' => $device->id,
            'device_name_id' => $device_name->id,
            'name' => $data['spec']
        ]);
        return [
            'device_id' => $device->id,
            'device_name_id' => $device_name->id,
            'spec_id' => $spec->id,
            'rent_type_id' => $rent_type->id
        ];
    }

    /**
     * @param Request $request
     * @return int(1改变2不改变)
     */
    public function checkIsChange(Request $request)
    {
        if($this['type'] == 1) return 2;
        $devices = $request->input('devices');
    }

    public function order_devices()
    {
        return $this->hasMany('App\Models\OrderDevice', 'order_id');
    }
}
