<?php

namespace App\Models;

use App\Components\Functions;
use App\Events\LogAction;
use App\Jobs\CreateRoomConservation;
use App\Jobs\CreateRoomConservationV2;
use App\Jobs\DeleteRoomConversation;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;


class Room extends Model
{
    //
    use SoftDeletes;
    use LogsActivity;

    protected static $logAttributes = ['*'];

    const FULL = 1;
    const AVAILABLE = 2;
    const NEED_MORE = 3;

    const ONE_MONTH_PERIOD = 1;
    const TWO_MONTH_PERIOD = 2;
    const THREE_MONTH_PERIOD = 3;
    const SIX_MONTH_PERIOD = 4;
    const ONE_YEAR_PERIOD = 5;
    const FOUR_MONTH_PERIOD = 8;
    const FIVE_MONTH_PERIOD = 9;

    const START_PERIOD = 1;
    const LAST_PERIOD = 2;

    const IMAGE_LIVING_ROOM = 1;
    const IMAGE_BED_ROOM = 2;
    const IMAGE_KITCHEN = 3;
    const IMAGE_OTHER = 4;
    const IMAGE_WC = 5;

    protected $fillable = [
        'name',
        'floor',
        'size',
        'type',
        'price',
        'deposit',
        'debt',
        'status',
        'current_electric',
        'current_water',
        'current_renter',
        'hostel_id',
        'desc',
        'start_electric',
        'start_water',
        'created_at',
        'updated_at',
        'deleted_at',
        'date_available',
        'max_renters',
        'long',
        'width',
        'block_name',
        'is_empty',
        'lat',
        'lng',
        'is_display',
        'block_group',
        'is_start_remind'
    ];

    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at',
    ];

    public function reserves()
    {
        return $this->hasMany(RoomReservation::class, 'room_id', 'id');
    }

    public function beds()
    {
        return $this->hasMany(RoomBed::class, 'room_id', 'id');
    }

    public function getCurrentRenterDataAttribute()
    {
        $account = User::find($this->attributes['current_renter']);
        if ($account) {
            return $account;
        }

        return '';
    }

    public function items()
    {
        return $this->belongsToMany(Item::class, 'room_items', 'room_id', 'item_id')
            ->withPivot([
                'mover',
                'receiver',
                'number',
                'id',
                'room_id'
            ])
            ->withTimestamps();
    }

    public function ewMonth(Carbon $month)
    {
        return $this->hasMany(ElectricWater::class)->whereBetween('date_action',
            [
                $month->copy()->startOfMonth(),
                $month->copy()->endOfMonth()
            ]
        );
    }

    public function deposits()
    {
        return $this->hasMany(Deposit::class)
            ->where(function ($q) {
                $q->orHas('reserve');
                $q->orHas('contractValid');
            });
    }

    public function breaks()
    {
        return $this->hasMany(BreakHistory::class, 'id', 'room_id')->orderBy('breaks.id', 'desc');
    }

    public static function boot()
    {
        parent::boot();
        static::saved(function ($room) {
            self::updateEmptyRooms($room);
            self::updateRoomPrice($room);
            $userId = Functions::getCurrentUserId();
            dispatch(new CreateRoomConservationV2($room->id, $userId));

        });
        static::updated(function ($room) {
            self::updateEmptyRooms($room);

            $hostel = $room->hostel;
            if (!$hostel) {
                return;
            }
            if ($hostel->type_rent == Hostel::TYPE_RENT_ALL) {
                return;
            }
            $maxRenters = $room->max_renters;
            $numberBeds = $room->beds->count();

            if ($maxRenters > $numberBeds) {
                while ($numberBeds < $maxRenters) {
                    $numberBeds++;
                    RoomBed::create([
                        'name' => 'Giường ' . $numberBeds,
                        'hostel_id' => $room->hostel_id,
                        'room_id' => $room->id,
                        'status' => RoomBed::AVAILABLE,
                    ]);
                }
            }
        });
        static::created(function ($room) {
            self::updateEmptyRooms($room);

            $user = Functions::getCurrentUser();
            event(new LogAction([
                'type' => 'create-room',
                'user_id' => optional($user)->id,
                'object_id' => $room->id,
                'hostel_id' => $room->hostel->id,
                'room_id' => $room->id,
                'properties' => $room->toArray(),
                'desc' => '{'.$user->name.'} đã tạo phòng {'.$room->name.'}, nhà {'.$room->hostel->name.'}'
            ]));
        });

        static::deleted(function ($room) {
            self::updateEmptyRooms($room);
            self::updateRoomPrice($room);
            Deposit::query()->where('room_id', $room->id)->delete();

            $user = Functions::getCurrentUser();
            event(new LogAction([
                'type' => 'delete-room',
                'user_id' => optional($user)->id,
                'object_id' => $room->id,
                'hostel_id' => $room->hostel->id,
                'room_id' => $room->id,
                'properties' => $room->toArray(),
                'desc' => '{'.$user->name.'} đã xóa phòng {'.$room->name.'}, nhà {'.$room->hostel->name.'}'
            ]));
        });


    }

    public static function updateRoomPrice($room)
    {
        $hostelId = $room->hostel_id;
        $hostel = Hostel::find($hostelId);
        if (!$hostel) {
            return;
        }
        $prices = Functions::getPriceHostelForFinding($hostel);

        if (!empty($prices)) {
            $smallest = $prices['smallest'];
            $greatest = $prices['greatest'];
            if (!is_null($smallest)) {
                $hostel->min_price = $smallest;
            }
            if (!is_null($greatest)) {
                $hostel->max_price = $greatest;
            }
            $hostel->save();
//            $hostel->
        } else {
            if (!is_null($hostel->greatest_price)) {
                $hostel->max_price = $hostel->greatest_price;
            }

            if (!is_null($hostel->smallest_price)) {
                $hostel->min_price = $hostel->smallest_price;
            }
            $hostel->save();
        }
    }

    public static function updateEmptyRooms($room)
    {
        if ($room) {

            Functions::updateHostelEmptyRooms($room->hostel_id);
        }
    }

    public function getIsEmptyAttribute()
    {
        $roomId = $this->attributes['id'];

        $cnt = RenterRoom::query()->where('room_id', $roomId)->count();
        if ($cnt) {
            return 'Đã thuê';
        }

        return 'Còn trống';
    }

    public function scopeDisplay($q)
    {
        return $q->where('is_display', true);
    }

    public function getStatusTextAttribute()
    {
        $type = $this->attributes['status'];

        if ($type == Room::FULL) {
            return 'Đã đầy';
        } else if ($type == Room::AVAILABLE) {
            return 'Còn trống';
        } else if ($type == Room::NEED_MORE) {
            return 'Cần ở ghép';
        }

        return 'Chưa rõ';
    }

    public function getStatusHtmlTextAttribute()
    {
        $type = $this->attributes['status'];

        if ($type == Room::FULL) {
            return '<label class="label label-danger">Đã đầy</label>';
        } else if ($type == Room::AVAILABLE) {
            return '<label class="label label-success">Còn trống</label>';
        } else if ($type == Room::NEED_MORE) {
            return '<label class="label label-warning">Cần ở ghép</label>';
        }

        return '<label class="label label-primary">Chưa rõ</label>';
    }

    public function getTypeTextAttribute()
    {
//        $type = $this->attributes['type'];
//        $roomType = \DB::table('room_types')->where('id', $type)->first();
//        if ($roomType) {
//            return $roomType->name;
//        }

        return 'Chưa xác định';
    }

    public function hostel()
    {
        return $this->belongsTo('App\Models\Hostel')->withTrashed();
    }

    public function roomType()
    {
        return $this->belongsTo(RoomType::class, 'type', 'id');
    }

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

    public function images()
    {
        return $this->hasMany('room_images', 'room_id');
    }

    public function contracts()
    {
        return $this->hasMany(Contract::class);
    }

    public function contractsValid()
    {
        return $this->hasMany(Contract::class)->where('contracts.status', '<>', Contract::LIQUIDATED);
    }

    public function amenities()
    {
        return $this->belongsToMany(Amenity::class, 'room_amenities', 'room_id', 'amenity_id');
    }

    public function renters()
    {
        return $this->belongsToMany(Renter::class, 'renter_rooms', 'room_id', 'user_id', 'id', 'user_id');
    }

    public function getImageAttribute()
    {
        $images = \DB::table('room_images')->where('room_id', $this->attributes['id'])->first();
        if ($images) {
            return '/files/' . $images->image;
        }
        return null;
    }

    public function scopeIsWithinMaxDistance($query, $coordinates, $radius = 5)
    {
        $haversine = "(6371 * acos(cos(radians(" . $coordinates['lat'] . ")) 
                    * cos(radians(`lat`)) 
                    * cos(radians(`lng`) 
                    - radians(" . $coordinates['lng'] . ")) 
                    + sin(radians(" . $coordinates['lat'] . ")) 
                    * sin(radians(`lat`))))";

        return $query->select('*')
            ->selectRaw("{$haversine} AS distance")
            ->whereRaw("{$haversine} < ?", [$radius]);
    }

    public function getFirstImageAttribute()
    {
        $id = $this->attributes['id'];
        $image = \DB::table('room_images')->where('room_id', $id)->first();
        if ($image) {
            return '/files/' . $image->image;
        }

        return '/frontend3/assets/img/placeholder.png';

    }

    public function roomBed()
    {
        return $this->hasMany(RoomBed::class, 'room_id', 'id');
    }
}
