<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Cache;

class ItemReference extends Model
{
    use HasFactory, Compoships;

    protected $table = 'item_reference';
    protected $primaryKey = 'id';
    protected $fillable = ['item_id','item_variant_id','number','unit'];

    public function images()
    {
        return $this->hasMany(ItemImage::class, 'item_id', 'item_id');
    }

    public function item()
    {
        return $this->belongsTo(Items::class)->with("brand", "gender", "category");
    }

    public function itemVariant()
    {
        return $this->belongsTo(ItemVariant::class);
    }

    public function variants()
    {
        $model = ItemVariant::where('item_id', $this->item_id)->get();
        return $model;
    }

    public function location()
    {
        return $this->belongsTo(Location::class, "location_id");
    }

    public function stocks()
    {
        return $this->hasMany(Stock::class, ["item_id", "item_variant_id"], ["item_id", "item_variant_id"])
            ->with("location");
    }

    public function bucketStocks()
    {
        return $this->hasMany(BucketStock::class)->with("bucket");
        // ->where("quantity",">",0);
    }

    public function promotion()
    {
        return $this->belongsToMany(Promotion::class, "promotion_item", "item_id", "promotion_id");
    }

    public function price()
    {
        $user = auth()->user();

        [$location_id, $is_consignment] = Cache::remember(
            "employee_user_" . optional($user)->id,
            60,
            function () use ($user) {
                if (!$user) {
                    return [10, false];
                }

                $employee = $user->employee;
                $location_id = $employee->location_id ?? 10;
                $location = $employee->location;

                $is_consignment = (bool) optional($location)->is_consignment
                    && optional($location)->id != 9;

                return [$location_id, $is_consignment];
            }
        );

        return $this->hasOne(Discount::class, 'id', 'item_reference_id')
            ->leftJoin('discount_items', 'discount_items.discount_id', '=', 'discounts.id')
            ->where('discounts.type', 'price')
            ->where(function ($query) {
                $query->where('valid_at', '<=', now())
                    ->orWhereNull('valid_at');
            })
            ->where(function ($query) {
                $query->where('expired_at', '>', now())
                    ->orWhereNull('expired_at');
            })
            ->where(function ($query) use ($location_id, $is_consignment) {
                if (!$is_consignment) {
                    $query->whereNull('discounts.location_id');
                }

                if ($location_id) {
                    $query->orWhere('discounts.location_id', $location_id);
                }
            })
            ->orderByDesc('discounts.created_at')
            ->select([
                'discount_items.item_reference_id',
                'discount_items.price',
            ]);
    }



    public function discount()
    {

        $user = auth()->user();
        list($location_id, $is_consignment) = Cache::remember("employee_user_".$user->id, 60 * 60 * 24, function(){

            $employee = @$user->employee;
            $location_id = @$employee->location_id ?? 10;
            $location = @$employee->location;
            $is_consignment = (boolean) @$location->is_consignment && $location->id != 9;
            return [$location_id, $is_consignment];

        });

// Log::info([$location_id,  $is_consignment]);

        return $this->hasOne(Discount::class,DB::raw("discount_items.item_reference_id"))
            ->leftJoin("discount_items","discounts.id","=","discount_id")
            ->where("discounts.type","discount")
            ->orderBy("discounts.created_at","desc")
            ->where(function($query){
                    $query->where("valid_at", "<=", Carbon::now())
                           ->orWhereNull("valid_at");
             })
            ->where(function($query){
                    $query->where("expired_at", ">", Carbon::now())
                           ->orWhereNull("expired_at");
             })

            ->where(function($query) use ($location_id, $is_consignment){
                if (!$is_consignment)
                    $query->whereNull("discounts.location_id");
                if ($location_id)
                    $query->orWhere("discounts.location_id", $location_id);
            })
            ->select("item_reference_id","price");
    }


    public function point()
    {
        return $this->hasOne(CustomerPointRule::class);
    }

    public function promotion3()
    {
        $now = Carbon::now()->format('Y-m-d');
        $promotions = "select DISTINCT ON (item_id) item_id as item_reference_id, name, note from
            promotions left join promotion_item on promotions.id = promotion_id
            where (valid_date is null or valid_date::date <= '$now')
            and (expired_date is null or expired_date::date >= '$now')
            and type <> 'POINT'";

        $points = "select item_reference_id, array_agg((case when qty is null then '' else (qty || ': ') end) ||  point || ' Point' order by point asc) as name
            from customer_point_rules
            group by item_reference_id";

        return $this->hasOne(ItemReference::class,"id")
            ->select('item_reference.id as item_reference_id',DB::raw("(case when points.name is null then promotions.name else array_to_string(points.name,', ') end) as promotion"),'promotions.note as promotion_note')
            ->leftJoin(DB::raw("(" . $promotions . ") as promotions"), "promotions.item_reference_id", "=", "item_reference.id")
            ->leftJoin(DB::raw("(" . $points . ") as points"), "points.item_reference_id", "=", "item_reference.id");
    }

    public function promotion2()
    {
        $now = Carbon::now()->format('Y-m-d');
        $promotions = "select DISTINCT ON (item_id) item_id, name, note from
        promotions left join promotion_item on promotions.id = promotion_id
        where (valid_date is null or valid_date::date <= '$now')
        and (expired_date is null or expired_date::date >= '$now')
        and item_id = $this->id
        and type <> 'POINT'";

        $points = "select item_reference_id, array_agg((case when qty is null then '' else (qty || ': ') end) ||  point || ' Point' order by point asc) as name
        from customer_point_rules
        where item_reference_id = $this->id
        group by item_reference_id";

        $result = DB::table('item_reference')
            ->select(DB::raw("(case when points.name is null then promotions.name else array_to_string(points.name,', ') end) as promotion"),
            'promotions.note as promotion_note')
            ->leftJoin(DB::raw("(" . $promotions . ") as promotions"), "promotions.item_id", "=", "item_reference.id")
            ->leftJoin(DB::raw("(" . $points . ") as points"), "points.item_reference_id", "=", "item_reference.id")
            ->where('item_reference.id', $this->id)
            ->first();

        return $result;
    }
}
