<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Discount extends Model
{
    public $timestamps = false;

    protected $guarded = ['id'];
    static $discountUserTypes = ['all_users', 'special_users'];

    static $discountSource = ['all', 'course', 'bundle', 'category', 'meeting', 'product', 'event', 'meeting_package'];
    static $panelDiscountSource = ['all', 'course', 'bundle', 'meeting', 'product'];
    static $discountSourceAll = 'all';
    static $discountSourceCourse = 'course';
    static $discountSourceCategory = 'category';
    static $discountSourceMeeting = 'meeting';
    static $discountSourceProduct = 'product';
    static $discountSourceBundle = 'bundle';
    static $discountSourceEvent = 'event';
    static $discountSourceMeetingPackage = 'meeting_package';

    static $discountTypes = ['percentage', 'fixed_amount'];
    static $discountTypePercentage = 'percentage';
    static $discountTypeFixedAmount = 'fixed_amount';

    public function creator()
    {
        return $this->belongsTo('App\User', 'creator_id', 'id');
    }

    public function discountUsers()
    {
        return $this->hasOne('App\Models\DiscountUser', 'discount_id', 'id');
    }

    public function discountCourses()
    {
        return $this->hasMany('App\Models\DiscountCourse', 'discount_id', 'id');
    }

    public function discountBundles()
    {
        return $this->hasMany('App\Models\DiscountBundle', 'discount_id', 'id');
    }

    public function discountEvents()
    {
        return $this->hasMany('App\Models\DiscountEvent', 'discount_id', 'id');
    }

    public function discountMeetingPackages()
    {
        return $this->hasMany('App\Models\DiscountMeetingPackage', 'discount_id', 'id');
    }

    public function discountCategories()
    {
        return $this->hasMany('App\Models\DiscountCategory', 'discount_id', 'id');
    }

    public function discountGroups()
    {
        return $this->hasMany('App\Models\DiscountGroup', 'discount_id', 'id');
    }

    public function discountRemain()
    {
        $count = $this->count;

        $orderItems = OrderItem::where('discount_id', $this->id)
            ->groupBy('order_id')
            ->get();

        foreach ($orderItems as $orderItem) {
            if (!empty($orderItem) and !empty($orderItem->order) and $orderItem->order->status == 'paid') {
                $count = $count - 1;
            }
        }

        return ($count > 0) ? $count : 0;
    }

    public function salesStats()
    {
        $count = 0;
        $amount = 0;

        $orderItems = OrderItem::where('discount_id', $this->id)
            ->groupBy('order_id')
            ->get();

        foreach ($orderItems as $orderItem) {
            if (!empty($orderItem) and !empty($orderItem->order) and $orderItem->order->status == 'paid') {
                $count = $count + 1;
                $amount = $amount + $orderItem->total_amount;
            }
        }

        return [
            'count' => $count,
            'amount' => $amount,
        ];
    }

    public function checkValidDiscount($user = null)
    {
        if ($this->expired_at < time()) {
            return trans('update.discount_code_has_expired'); // expired
        }

        if (empty($user)) {
            $user = auth()->user();
        }

        $carts = Cart::where('creator_id', $user->id)->get();


        if (($this->source == self::$discountSourceCourse or $this->source == self::$discountSourceCategory)) {
            $webinarCount = array_filter($carts->pluck('webinar_id')->toArray());

            if (empty($webinarCount) or count($webinarCount) < 1) {
                return trans('update.discount_code_is_for_courses_error');
            }
        } elseif ($this->source == self::$discountSourceBundle) {
            $bundleCount = array_filter($carts->pluck('bundle_id')->toArray());

            if (empty($bundleCount) or count($bundleCount) < 1) {
                return trans('update.discount_code_is_for_bundles_error');
            }
        }  elseif ($this->source == self::$discountSourceEvent) {
            $eventTicketCount = array_filter($carts->pluck('event_ticket_id')->toArray());

            if (empty($eventTicketCount) or count($eventTicketCount) < 1) {
                return trans('update.discount_code_is_for_events_error');
            }
        } elseif ($this->source == self::$discountSourceMeetingPackage) {
            $meetingPackagesCount = array_filter($carts->pluck('meeting_package_id')->toArray());

            if (empty($meetingPackagesCount) or count($meetingPackagesCount) < 1) {
                return trans('update.discount_code_is_for_meeting_package_error');
            }
        } elseif ($this->source == self::$discountSourceProduct) {
            $productCount = array_filter($carts->pluck('product_order_id')->toArray());

            if (empty($productCount) or count($productCount) < 1) {
                return trans('update.discount_code_is_for_products_error');
            }
        } elseif ($this->source == self::$discountSourceMeeting) {
            $meetingCount = array_filter($carts->pluck('reserve_meeting_id')->toArray());

            if (empty($meetingCount) or count($meetingCount) < 1) {
                return trans('update.discount_code_is_for_meetings_error');
            }
        }

        if ($this->source == self::$discountSourceCourse and count($this->discountCourses)) {
            $discountWebinarsIds = $this->discountCourses()->pluck('course_id')->toArray();
            $hasSpecialWebinars = false;

            foreach ($carts as $cart) {
                $webinar = $cart->webinar;
                if (!empty($webinar) and in_array($webinar->id, $discountWebinarsIds)) {
                    $hasSpecialWebinars = true;
                }
            }

            if (!$hasSpecialWebinars) {
                return trans('update.your_coupon_is_valid_for_another_course');
            }
        }

        if ($this->source == self::$discountSourceBundle and count($this->discountBundles)) {
            $discountBundlesIds = $this->discountBundles()->pluck('bundle_id')->toArray();
            $hasSpecialBundles = false;

            foreach ($carts as $cart) {
                $bundle = $cart->bundle;
                if (!empty($bundle) and in_array($bundle->id, $discountBundlesIds)) {
                    $hasSpecialBundles = true;
                }
            }

            if (!$hasSpecialBundles) {
                return trans('update.your_coupon_is_valid_for_another_bundle');
            }
        }

        if ($this->source == self::$discountSourceEvent and count($this->discountEvents)) {
            $discountEventsIds = $this->discountEvents()->pluck('event_id')->toArray();
            $hasSpecialEvents = false;

            foreach ($carts as $cart) {
                $eventTicket = $cart->eventTicket;

                if (!empty($eventTicket) and in_array($eventTicket->event_id, $discountEventsIds)) {
                    $hasSpecialEvents = true;
                }
            }

            if (!$hasSpecialEvents) {
                return trans('update.your_coupon_is_valid_for_another_events');
            }
        }

        if ($this->source == self::$discountSourceMeetingPackage and count($this->discountMeetingPackages)) {
            $discountMeetingPackagesIds = $this->discountMeetingPackages()->pluck('meeting_package_id')->toArray();
            $hasSpecialMeetingPackages = false;

            foreach ($carts as $cart) {
                $meetingPackage = $cart->meetingPackage;

                if (!empty($meetingPackage) and in_array($meetingPackage->id, $discountMeetingPackagesIds)) {
                    $hasSpecialMeetingPackages = true;
                }
            }

            if (!$hasSpecialMeetingPackages) {
                return trans('update.your_coupon_is_valid_for_another_meeting_packages');
            }
        }

        if ($this->source == self::$discountSourceProduct) {
            $hasSpecialProducts = false;

            foreach ($carts as $cart) {
                if (!empty($cart->productOrder)) {
                    $product = $cart->productOrder->product;

                    if (!empty($product) and ($this->product_type == 'all' or $this->product_type == $product->type)) {
                        $hasSpecialProducts = true;
                    }
                }
            }

            if (!$hasSpecialProducts) {
                return trans('update.your_coupon_is_valid_for_another_products_type');
            }
        }

        if ($this->source == self::$discountSourceCategory) {
            $categoriesIds = ($this->discountCategories) ? $this->discountCategories()->pluck('category_id')->toArray() : [];
            $hasSpecialCategories = false;

            foreach ($carts as $cart) {
                $webinar = $cart->webinar;
                if (!empty($webinar) and in_array($webinar->category_id, $categoriesIds)) {
                    $hasSpecialCategories = true;
                }
            }

            if (!$hasSpecialCategories) {
                return trans('update.your_coupon_is_valid_for_another_category');
            }
        }

        if ($this->type == 'special_users') {
            $userDiscount = DiscountUser::where('user_id', $user->id)
                ->where('discount_id', $this->id)
                ->first();

            if (empty($userDiscount)) {
                return trans('cart.coupon_invalid'); // not for this user
            }
        }


        if (!empty($this->minimum_order)) { // check user orders minimum amounts
            $totalCartsPrice = Cart::getCartsTotalPrice($carts);

            if ($this->minimum_order > $totalCartsPrice) {
                return trans('update.discount_code_minimum_order_error', ['min_order' => $this->minimum_order]); // the minimum order is less than the discount amount
            }
        }

        if (!empty($this->discountGroups) and count($this->discountGroups)) {
            $groupsIds = $this->discountGroups()->pluck('group_id')->toArray();

            if (empty($user->userGroup) or !in_array($user->userGroup->group_id, $groupsIds)) {
                return trans('update.discount_code_group_error'); // this user is not in specific group
            }
        }

        if ($this->for_first_purchase) {
            $checkIsFirstPurchase = Sale::where('buyer_id', $user->id)
                ->whereNull('refund_at')
                ->count();

            if ($checkIsFirstPurchase > 0) {
                return trans('update.discount_code_for_first_purchase_error'); // This discount code for first purchase.
            }
        }

        $usedCount = 0;
        $orderItems = OrderItem::where('discount_id', $this->id)
            ->groupBy('order_id')
            ->get();

        foreach ($orderItems as $orderItem) {
            if (!empty($orderItem) and !empty($orderItem->order) and $orderItem->order->status == 'paid') {
                $usedCount += 1;
            }
        }

        if ($usedCount >= $this->count) {
            return trans('update.discount_code_used_count_error'); // The number of uses of this code has expired.
        }

        return 'ok';
    }
}
