<?php

namespace App\Models;

use App\Helpers\Price;
use App\Models\Dictionary\Area;
use App\Models\Dictionary\District;
use App\Models\Scopes\YearScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;

#[ScopedBy([YearScope::class])]
class Order extends Model
{


    use SoftDeletes;
    const DEFAULT_SORT_BY = 'created_at';

    const STATUS_NEW = 1;
    const STATUS_NOT_READY = 2;
    const STATUS_READY_NO_MAF = 3;
    const STATUS_READY_TO_MOUNT = 4;
    const STATUS_IN_MOUNT = 5;
    const STATUS_DUTY = 6;
    const STATUS_READY_TO_HAND_OVER = 7;
    const STATUS_NOT_HANDED_OVER_WITH_NOTES = 8;
    const STATUS_HANDED_OVER_WITH_NOTES = 9;
    const STATUS_HANDED_OVER = 10;
    const STATUS_NO_MAF = 11;
    const STATUS_PROBLEM = 12;

    //ПЛ не готова; ПЛ готова нет МАФ; Готов к монтажу; В монтаже; Долг;Готов к сдаче;Не сдан, замечания;Сдан с замечаниями;Сдан;Проблема

    const STATUS_NAMES = [
        self::STATUS_NEW => 'Новая',
        self::STATUS_NOT_READY => 'Не готова',
        self::STATUS_READY_NO_MAF => 'Готова, нет МАФ',
        self::STATUS_READY_TO_MOUNT => 'Готова к монтажу',
        self::STATUS_IN_MOUNT => 'В монтаже',
        self::STATUS_DUTY => 'Долг',
        self::STATUS_READY_TO_HAND_OVER => 'Готова к сдаче',
        self::STATUS_NOT_HANDED_OVER_WITH_NOTES => 'Не сдана, замечания',
        self::STATUS_HANDED_OVER_WITH_NOTES => 'Сдана с замечаниями',
        self::STATUS_HANDED_OVER => 'Сдана',
        self::STATUS_NO_MAF => 'Отсутствуют МАФ',
        self::STATUS_PROBLEM => 'Проблема',
    ];


    // set year attribute to current selected year
    protected static function boot(): void
    {
        parent::boot();
        static::creating(function($attributes) {
            if(!isset($attributes->year)) {
                $attributes->year = year();
            }
        });
    }

    protected $fillable = [
        'year',
        'name',
        'user_id',
        'district_id',
        'area_id',
        'object_address',
        'object_type_id',
        'comment',
        'installation_date',
        'ready_date',
        'brigadier_id',
        'order_status_id',
        'tg_group_name',
        'tg_group_link',
        'ready_to_mount',
    ];

    public $appends = ['common_name', 'products_with_count'];

    public function products_sku(): HasMany
    {
        return $this->hasMany(ProductSKU::class, 'order_id', 'id');
    }

    public function products(): HasManyThrough
    {
        return $this->hasManyThrough(
            Product::class,
            ProductSKU::class,
            'order_id',
            'id',
            'id',
            'product_id');
    }


    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id', 'id');
    }

    public function district(): BelongsTo
    {
        return $this->belongsTo(District::class);
    }

    public function area(): BelongsTo
    {
        return $this->belongsTo(Area::class);
    }

    public function objectType(): BelongsTo
    {
        return $this->belongsTo(ObjectType::class);
    }

    public function brigadier(): BelongsTo
    {
        return $this->belongsTo(User::class, 'brigadier_id', 'id');
    }

    public function orderStatus(): BelongsTo
    {
        return $this->belongsTo(OrderStatus::class);
    }

    public function photos(): BelongsToMany
    {
        return $this->belongsToMany(File::class, 'order_photo');
    }

    public function documents(): BelongsToMany
    {
        return $this->belongsToMany(File::class, 'order_document');
    }

    public function statements(): BelongsToMany
    {
        return $this->belongsToMany(File::class, 'order_statement');
    }



    public function getNeeds(): array
    {
        $needs = [];
        foreach ($this->products_sku as $sku) {
            if($sku->maf_order) continue;
            $needs[$sku->product_id]['needs'] = (isset($needs[$sku->product_id])) ? $needs[$sku->product_id]['needs'] + 1 : 1;
        }

        foreach ($needs as $productId => $quantity) {
            $needs[$productId]['sku'] = MafOrder::query()
                ->where('maf_orders.product_id', $productId)
                ->sum('maf_orders.in_stock');
        }
        return $needs;
    }

    public function recalculateReadyToMount(): void
    {
        $result = true;

        foreach ($this->getNeeds() as $need) {
            if($need['sku'] < $need['needs']) {
                $result = false;
                break;
            }
        }

       $this->update(['ready_to_mount' => ($result) ? 'Да' : 'Нет']);
    }

    public function autoChangeStatus(): void
    {
        if(($this->products_sku->count() < 1)
            && ($this->order_status_id !== self::STATUS_NEW)
        ) {
            $this->update(['order_status_id' => self::STATUS_NO_MAF]);
            return;
        }

        if(($this->order_status_id === self::STATUS_READY_TO_MOUNT)
            && ($this->brigadier_id !== null)
            && ($this->installation_date !== null)
        ) {
            $allMafConnected = true;
            foreach ($this->products_sku as $sku) {
                if($sku->maf_order) continue;
                $allMafConnected = false;
            }

            if($allMafConnected) {
                $this->update(['order_status_id' => self::STATUS_IN_MOUNT]);
            }
        }

    }

    public function commonName(): Attribute
    {
        return Attribute::make(
            get: fn($value) => (string) $this->object_address . ', ' . $this->area->name . ', ' . $this->district->shortname,
        );
    }

    public function productsWithCount(): Attribute
    {
        $products = $this->products_sku;
        $ret = [];

        foreach ($products as $product) {
            if(isset($ret[$product->product->id])) {
                $ret[$product->product->id]['count'] += 1;
            } else {
                $ret[$product->product->id] = [
                    'name' => $product->product->article,
                    'count' => 1,
                ];
            }
            if($product->maf_order?->order_number) {

                $ret[$product->product->id]['order_numbers'][] = $product->maf_order?->order_number;
            }
        }
        $s = '';

        foreach ($ret as $product) {
            ;
            $order_numbers = (isset($product['order_numbers'])) ? ' (' . implode(', ', array_unique($product['order_numbers'])) . ')' : '';
            $s .= '<div>' . $product['name'] . ' - ' . $product['count'] . $order_numbers . '</div>';
        }

        return Attribute::make(
            get: fn($value) => (string) $s,
        );
    }


}

