<?php

namespace App;

use App\Components\Functions;
use App\Jobs\AfterRegisterOwner;
use App\Jobs\SendNotificationUserNotRequest;
use App\Jobs\UpdateConversationMemberNames;
use App\Models\Account;
use App\Models\AuthLoginLog;
use App\Models\Config;
use App\Models\Contract;
use App\Models\District;
use App\Models\Hostel;
use App\Models\HostelPostCrawl;
use App\Models\Lead;
use App\Models\Province;
use App\Models\RenterRoom;
use App\Models\Room;
use App\Models\TypeCollect;
use App\Models\TypeSpend;
use App\Models\UserPackage;
use App\Models\UserPackageFindHostel;
use App\Models\Ward;
use App\Models\Warehouse;
use App\Models_v2\FindSession;
use App\Models_v2\Package;
use App\Notifications\SendEmailPassword;
use Carbon\Carbon;
use App\Traits\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use Notifiable;
    use SoftDeletes;
    use HasRoles;
    use LogsActivity;

    protected static $logAttributes = ['*'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */

    protected $guard_name = 'backend';

    const OWNER = 1;
    const RENTER = 2;
    const ADMIN = 4;
    const EDITOR = 5;
    const STAFF = 6;
    const SYSTEM = 7;
    const PARTNER = 8;
    const PARTNER_STAFF = 9;


    const ACTIVE = 0;
    const IN_ACTIVE = 1;
    const COLLABORATOR = 3;


    const NOT_CONFIRM = 0;
    const CONFIRM = 1;

    const FROM_WEB = 0;
    const FROM_ANDROID = 1;
    const FROM_IOS = 2;

    const BRANCH_MANAGE = 0;
    const BRANCH_FIND = 1;

    const PAYMENT_TRIAL = 0; // dùng thử
    const PAYMENT_PAYING = 1; // đang trả tiền
    const PAYMENT_OVER = 2; // Quá hạn
    const PAYMENT_NOT_USE = 3; //Không sử dụng nữa

    const REFER_STATUS_NOT_SUCCESS = 1; // giới thiệu ko thành công
    const REFER_STATUS_SUCCESS = 2; // giới thiệu thành công

//- Đã tạo nhà & xác thực
//- Đã tạo nhà & chưa xác thực
//- Chưa tạo nhà
//- Đã tạo request tìm kiếm
    const REFER_REASON_CREATED_NOT_CONFIRM = 2;
    const REFER_REASON_NOT_CREATED = 3;
    const REFER_REASON_NOT_CREATE_REQUEST = 4;

    const TYPE_DISPLAY_MONEY_INFO_CURRENT_MONTH = 0;
    const TYPE_DISPLAY_MONEY_INFO_PREVIOUS_MONTH = 1;


    const TYPE_ARR = [
        User::OWNER => 'Chủ trọ',
        User::RENTER => 'Người thuê trọ',
        User::ADMIN => 'Quản trị',
        User::EDITOR => 'Biên tập viên',
        User::STAFF => 'Nhân viên',
        User::SYSTEM => 'Hệ thống',
        User::PARTNER => 'Đối tác',
        User::PARTNER_STAFF => 'Nhân viên đối tác'
    ];


    protected $fillable = [
        'name',
        'email',
        'password',
        'balance',
        'type',
        'phone',
        'register_by',
        'facebook_id',
        'zalo_id',
        'google_id',
        'apple_id',
        'image',
        'phone',
        'birthday',
        'address',
        'province_id',
        'district_id',
        'type_display_money_info',
        'ward_id',
        'gender',
        'id_number',
        'temp_residence',
        'residence',
        'folk',
        'nation',
        'religion',
        'number_view_leads',
        'password',
        'remember_token',
        'created_at',
        'updated_at',
        'collect',
        'spend',
        'status',
        'number_hostels',
        'number_rooms',
        'code',
        'android_token',
        'ios_token',
        'is_owner_first',
        'status_email',
        'status_phone',
        'job',
        'job_address',
        'residence_province',
        'residence_district',
        'residence_ward',
        'academic_level',
        'temp_residence_ward',
        'expire_date_owner',
        'temp_residence_province',
        'temp_residence_district',
        'first_name',
        'last_name',
        'first_add_renter',
        'send_notification_first',
        'date_send_notification',
        'is_connect_facebook',
        'is_connect_google',
        'is_fb_first',
        'token_active',
        'token_forget_password',
        'webpush_token',
        'from',
        'province_name',
        'district_name',
        'ward_name',
        'staff_owner_id',
        'is_over_date',
        'package_id',
        'refer_phone',
        'refer_id',
        'partner_company',
        'partner_number_staff',
        'partner_refer',
        'account_kit_code',
        'day_remind_empty_room',
        'remind_empty_room_interval',
        'allow_renter_make_group',
        'allow_renter_view_hostel_group',
        'allow_renter_view_room_group',
        'allow_renter_momo_payment',
        'domain',
        'day_generate_money_info',
        'token',
        'country_phone_code',
        'number_interacts',
        'is_accept_news',
        'branch_app',
        'last_login_at',
        'last_find_at',
        'payment_status',
        'is_agent',
        'refer_code',
        'aff_link',

        'refer_date',
        'refer_status',
        'refer_reason',
        'number_zalo_mess',

        'otp',
        'otp_expire'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

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

    public static function boot()
    {
        parent::boot();
        static::creating(function ($item) {
            if (!empty($item->refer_id)) {
                $item->refer_date = Carbon::now();
            }
        });
        static::created(function ($item) {

            if ($item->type == User::RENTER) {
                User::query()
                    ->where('id', $item->id)
                    ->update([
                        'refer_status' => User::REFER_STATUS_NOT_SUCCESS,
                        'refer_reason' => User::REFER_REASON_NOT_CREATE_REQUEST
                    ]);
            }
            if ($item->type == User::OWNER) {

                User::query()
                    ->where('id', $item->id)
                    ->update([
                        'refer_status' => User::REFER_STATUS_NOT_SUCCESS,
                        'refer_reason' => User::REFER_REASON_NOT_CREATED
                    ]);


                dispatch(new AfterRegisterOwner($item));
//				$package = Package::query()->first();
//				UserPackageFindHostel::create( [
//					'user_id'          => $item->id,
//					'package_id'       => optional( $package )->id,
//					'price_per_month'  => optional( $package )->price,
//					'number_interacts' => optional( $package )->number_interacts,
//					'transaction_fee'  => optional( $package )->transaction_fee,
//				] );

                $cntTypeSpend = TypeSpend::query()
                    ->where('owner_id', $item->id)
                    ->count();

                if ($cntTypeSpend == 0) {
                    TypeSpend::create([
                        'owner_id' => $item->id,
                        'name' => 'Tiền nhà',
                        'is_default' => TypeSpend::TIEN_NHA,
                    ]);
                    TypeSpend::create([
                        'owner_id' => $item->id,
                        'name' => 'Tiền điện',
                        'is_default' => TypeSpend::TIEN_DIEN,
                    ]);
                    TypeSpend::create([
                        'owner_id' => $item->id,
                        'name' => 'Tiền nước',
                        'is_default' => TypeSpend::TIEN_NUOC,
                    ]);
                    TypeSpend::create([
                        'owner_id' => $item->id,
                        'name' => 'Tiền cọc',
                        'is_default' => TypeSpend::TIEN_COC,
                    ]);
                }

                TypeCollect::create([
                    'owner_id' => $item->id,
                    'name' => 'Tiền nhà',
                    'can_delete' => false,
                    'type' => TypeCollect::ROOM_PRICE
                ]);
                TypeCollect::create([
                    'owner_id' => $item->id,
                    'name' => 'Tiền cọc',
                    'can_delete' => false,
                    'type' => TypeCollect::DEPOSIT
                ]);
                TypeCollect::create([
                    'owner_id' => $item->id,
                    'name' => 'Tiền dịch vụ',
                    'can_delete' => false,
                    'type' => TypeCollect::SERVICE
                ]);

                $sample = \DB::table('samples')->where('id', 1)->first();
                if ($sample) {
                    Config::query()->updateOrCreate([
                        'owner_id' => $item->id,
                    ], [
                        'owner_id' => $item->id,
                        'voucher_collect' => $sample->voucher_collect,
                        'voucher_spend' => $sample->voucher_spend,
                        'contract' => $sample->contract
                    ]);
                }

                Functions::syncCrm($item);

//                if (!empty($item->email)) {
//                    \Newsletter::subscribe($item->email);
//                }

                Warehouse::create([
                    'name' => 'Kho tài sản',
                    'owner_id' => $item->id
                ]);
                $item->number_interacts = 20;
            }

            $provinceId = $item->province_id;
            $districtId = $item->district_id;
            $wardId = $item->ward_id;

            $provinceName = null;
            $districtName = null;
            $wardName = null;

            $province = \DB::table('province')->where('provinceid', $provinceId)->first();
            $district = \DB::table('district')->where('districtid', $districtId)->first();
            $ward = \DB::table('ward')->where('wardid', $wardId)->first();

            if ($province) {
                $provinceName = $province->name;
            }

            if ($district) {
                $districtName = $district->name;
            }

            if ($ward) {
                $wardName = $ward->name;
            }


            $item->province_name = $provinceName;
            $item->district_name = $districtName;
            $item->ward_name = $wardName;
            if ($item->branch_app == User::BRANCH_FIND) {
                $item->last_login_at = Carbon::now()->toDateTimeString();
            }
            $item->refer_code = str_random(5);
            if (empty($item->country_phone_code)) {
                $item->country_phone_code = '+84';
            }
            if (empty($item->aff_link)) {
                $item->aff_link = Functions::generateDynamicLinkAff($item);
            }
            $item->save();

            $jobNotificationNotRequest = (new SendNotificationUserNotRequest($item->id))->delay(Carbon::now()->addMinutes(30));
            dispatch($jobNotificationNotRequest);


        });

        static::updated(function ($item) {
            if ($item->type == User::OWNER) {
                if ($item->created_at->year >= 2020) {
                    Functions::syncCrm($item);
                }
            }

            if ($item->isDirty('name') || $item->isDirty('last_name') || $item->isDirty('first_name')) {
                $conversations = \DB::table('user_conversations')
                    ->where('user_id', $item->id)
                    ->pluck('conversation_id')
                    ->toArray();

                foreach ($conversations as $conversation) {
                    dispatch(new UpdateConversationMemberNames($conversation));
                }
            }

        });
    }


    public function scopeEditor($q)
    {
        return $q->where('type', User::EDITOR);
    }

    public function package()
    {
        return $this->belongsTo(UserPackage::class, 'id', 'user_id');
    }

    public function getOwnerInfoAttribute()
    {
        if ($this->attributes['type'] == User::RENTER) {
            $currentRenter = RenterRoom::where('user_id', $this->attributes['id'])->latest('id')->first();
            if (!$currentRenter) {
                return null;
            }

            $hostel = $currentRenter->hostel;
            if (!$hostel) {
                return null;
            }

            return $hostel->owner;
        }

        return null;
    }

    public function getAddressTextAttribute()
    {

        $addressDetail = $this->getAddressDetailAttribute();
        if (!empty($addressDetail)) {
            return $this->attributes['address'] . ', ' . $addressDetail;
        }


        return $this->attributes['address'];
    }

    public function getReferStatusTextAttribute()
    {

        if ($this->attributes['refer_status'] == self::REFER_STATUS_SUCCESS) {
            return 'Thành công';
        }
        return 'Chưa thành công';
    }

    public function getReferReasonTextAttribute()
    {

        if ($this->attributes['refer_reason'] == self::REFER_REASON_NOT_CREATED) {
            return 'Chưa tạo nhà trọ';
        }
        if ($this->attributes['refer_reason'] == self::REFER_REASON_CREATED_NOT_CONFIRM) {
            return 'Đã tạo nhà trọ nhưng chưa xác nhận';
        }
        if ($this->attributes['refer_reason'] == self::REFER_REASON_NOT_CREATE_REQUEST) {
            return 'Chưa tạo yêu cầu tìm kiếm';
        }
    }

    public function getAddressDetailAttribute()
    {
        $district = $this->attributes['district_id'];
        $province = $this->attributes['province_id'];
        $ward = $this->attributes['ward_id'];
        $districtText = '';
        $provinceText = '';
        $wardText = '';

        if (!empty($district)) {
            $districtItem = Functions::getDistrictName($district);
            if ($districtItem) {
                $districtText = $districtItem->name . ', ';
            }
        }

        if (!empty($province)) {
            $provinceItem = Functions::getProvinceName($province);
            if ($provinceItem) {
                $provinceText = $provinceItem->name;
            }
        }

        if (!empty($ward)) {
            $wardItem = Functions::getWardName($ward);
            if ($wardItem) {
                $wardText = $wardItem->name . ', ';
            }
        }

        return trim($wardText . $districtText . $provinceText);
    }

    public function currentRoom()
    {
        return $this->belongsTo('App\Models\Room', 'current_room', 'id');
    }

    public function currentHostel()
    {
        return $this->belongsTo('App\Models\Hostel', 'current_hostel', 'id');
    }

    public function staffHostel()
    {
        return $this->belongsToMany(Hostel::class, 'staff_hostels', 'user_id', 'hostel_id')->withTimestamps();
    }

    public function bookmarks()
    {
        return $this->belongsToMany(Hostel::class, 'bookmarks', 'user_id', 'hostel_id')->withPivot('find_session_id');
    }

    public function staffHostelArr()
    {
        return $this->belongsToMany(Hostel::class, 'staff_hostels', 'user_id', 'hostel_id')->select('staff_hostels.hostel_id');
    }

    public function leads()
    {
        return $this->belongsToMany(Lead::class, 'lead_users', 'user_id', 'lead_id');
    }

    public function logoExist()
    {
        return $this->belongsTo(Config::class, 'id', 'owner_id')->whereNotNull('logo');
    }

//    public function getNameAttribute()
//    {
//        if(isset($this->attributes['name'])) {
//            $name = $this->attributes['name'];
//
//            if (empty($name)) {
//                return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
//            }
//
//            return $name;
//        }
//    }

//    public function setNameAttribute()
//    {
//        $firstName = '';
//        $lastName = '';
//        if(isset($this->attributes['first_name']))
//        {
//            $firstName = $this->attributes['first_name'];
//        }
//        if(isset($this->attributes['last_name']))
//        {
//            $lastName = $this->attributes['last_name'];
//        }
//        if(!empty(trim($firstName.' '.$lastName))) {
//            $this->attributes['name'] = $firstName . ' ' . $lastName;
//        }
//
//    }

    public function getNameTextAttribute()
    {
        $firstName = '';
        $lastName = '';


        if (isset($this->attributes['first_name'])) {
            $firstName = $this->attributes['first_name'];
        }
        if (isset($this->attributes['last_name'])) {
            $lastName = $this->attributes['last_name'];
        }

        $name = $firstName . ' ' . $lastName;

        if (!empty($this->attributes['name'])) {
            return $this->attributes['name'];
        }

        return $name;

    }

    public function getNameTextTypeAttribute()
    {
        $firstName = '';
        $lastName = '';
        $type = $this->attributes['type'];
        $typeText = '(chủ trọ)';
        if ($type == User::RENTER) {
            $typeText = '(khách thuê)';
        }

        if ($type == User::STAFF) {
            $typeText = '(nhân viên)';
        }


        if (isset($this->attributes['first_name'])) {
            $firstName = $this->attributes['first_name'];
        }
        if (isset($this->attributes['last_name'])) {
            $lastName = $this->attributes['last_name'];
        }

        $name = $firstName . ' ' . $lastName;

        if (!empty($firstName . $lastName)) {
            return $name . ' ' . $typeText;
        }

        return $this->attributes['name'] . ' ' . $typeText;

    }

    public function getFromTextAttribute()
    {
        $from = self::FROM_WEB;

        if (isset($this->attributes['from'])) {
            $from = $this->attributes['from'];
        }

        if ($from == self::FROM_ANDROID) {
            return 'Android';
        }

        if ($from == self::FROM_IOS) {
            return 'Ios';
        }

        return 'Web';
    }

    public function getBranchAppTextAttribute()
    {
        if (isset($this->attributes['branch_app'])) {
            if ($this->attributes['branch_app'] == User::BRANCH_FIND) {
                return 'Tìm khách';
            }
        }

        return 'Quản lý';
    }

    public function getRegisterByTextAttribute()
    {
        $data = $this->attributes['register_by'];

        if (empty($data)) {
            return '<label class="label label-warning">Tự đăng ký</label>';
        }

        $user = User::find($data);
        if ($user) {
            return '<label class="label label-succes">Tự đăng ký</label>';
        }

        return 'Chưa rõ';
    }

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

        if ($status == User::ACTIVE) {
            return '<label class="label label-success">Đã kích hoạt</label>';
        }

        return '<label class="label label-danger">Chưa kích hoạt</label>';
    }

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

        if ($status == User::PAYMENT_TRIAL) {
            return 'Dùng thử';
        }

        if ($status == User::PAYMENT_PAYING) {
            return 'Đang trả tiền';
        }
        if ($status == User::PAYMENT_OVER) {
            return 'Quá hạn';
        }
        if ($status == User::PAYMENT_NOT_USE) {
            return 'Không sử dụng nữa';
        }
    }

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

        if ($type == User::OWNER) {
            return 'Chủ trọ';
        } else if ($type == User::RENTER) {
            return 'Người thuê trọ';
        }

        return 'Người dùng';
    }

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

        if ($type) {
            return 'Đã xác nhận';
        }

        return 'Chưa xác nhận';
    }

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

        if ($type) {
            return 'Đã xác nhận';
        }

        return 'Chưa xác nhận';
    }

    public function getImageAttribute()
    {
        $image = $this->attributes['image'];

        if (empty($image)) {
            if (str_contains(request()->fullUrl(), 'api/v1')) {
                return null;
            }

            if (str_contains(request()->fullUrl(), 'api/v2')) {
                return null;
            }

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

        if (str_contains($image, 'http')) {
            return $image;
        }

        if (str_contains($image, '/files/')) {
            return '/files/' . str_replace('/files/', '', $image);
        }

        if (!str_contains($image, 'http') && !str_contains($image, '/files') && !str_contains($image, '/frontend3/')) {
            return '/files/' . $image;
        }

        return $image;
    }

    public function getDateJoinedAttribute()
    {
        $dateJoined = null;
        if ($this->attributes['type'] == User::RENTER) {
            $renterRoom = RenterRoom::where('user_id', $this->attributes['id'])->first();

            if ($renterRoom) {
                if (!empty($renterRoom->date_joined)) {
                    $dateJoined = Carbon::createFromFormat('Y-m-d H:i:s', $renterRoom->date_joined)->format('d/m/Y');
                } else {
                    $dateJoined = $renterRoom->created_at->format('d/m/Y');
                }
            }
        }

        return $dateJoined;
    }

    public function getResidenceStatusAttribute()
    {
        $status = null;
        if ($this->attributes['type'] == User::RENTER) {
            $renterRoom = RenterRoom::where('user_id', $this->attributes['id'])->first();

            if ($renterRoom) {
                $status = $renterRoom->residence_status;
            }
        }

        return $status;
    }

    public function getPackageFindHostelAttribute($user)
    {
        $owner = $user;
        if ($user->type == User::STAFF) {
            $owner = $user->owner;
        }

        if ($owner) {
            $package = UserPackageFindHostel::query()->where('user_id', $owner->id)->first();
            if ($package) {
                return [
                    'id' => $package->id,
                    'name' => $package->name
                ];
            }
        }

        return null;
    }

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new SendEmailPassword($token));
    }

    public function findSessions()
    {
        return $this->hasMany(FindSession::class, 'user_id', 'id');
    }

    public function hostels()
    {
        return $this->hasMany(Hostel::class, 'owner_id', 'id');
    }

    public function rooms()
    {
        return $this->hasManyThrough(Room::class, Hostel::class, 'owner_id', 'hostel_id', 'id', 'id');
    }

    public function loginLogs()
    {
        return $this->hasMany(AuthLoginLog::class, 'user_id', 'id')->orderBy('id', 'desc');
    }

    public function owner()
    {
        return $this->belongsTo(User::class, 'staff_owner_id', 'id');
    }

    public function excludeRecommends()
    {
        return $this->belongsToMany(Hostel::class, 'exclude_hostel_recommends', 'user_id', 'hostel_id');
    }

    public function packageFindHostel()
    {
        return $this->belongsTo(UserPackageFindHostel::class, 'id', 'user_id');
    }

    public function agentDistricts()
    {
        return $this->belongsToMany(District::class, 'agent_districts', 'user_id', 'district_id', 'id', 'districtid')->orderBy('district.name');
    }

    public function refer()
    {
        return $this->belongsTo(User::class, 'refer_id', 'id');
    }


    public function regions()
    {
        return $this->belongsToMany(Province::class, 'owner_regions', 'user_id', 'province_id', 'id', 'provinceid');
    }

    public function crawlWishlist()
    {
        return $this->belongsToMany(HostelPostCrawl::class, 'hostel_post_crawl_wishlists', 'user_id', 'hostel_post_crawl_id');
    }

    public function province()
    {
        return $this->belongsTo(Province::class, 'provinceid', 'province_id');
    }

    public function district()
    {
        return $this->belongsTo(District::class, 'districtid', 'district_id');
    }

    public function ward()
    {
        return $this->belongsTo(Ward::class, 'wardid', 'ward_id');
    }
}
