<?php

namespace App\Http\Controllers\Api\v2;

use App\Components\Functions;
use App\Models\District;
use App\Models\Hostel;
use App\Models\LeadUserTake;
use App\Models\Notification;
use App\Models\Province;
use App\Models\SearchLog;
use App\Models\UserPackageFindHostel;
use App\Models_v2\Conversation;
use App\Models_v2\DatabaseNotification;
use App\Models_v2\FindSession;
use App\Notifications\SearchHostel;
use App\Notifications\SearchHostelManageApp;
use App\Notifications\SearchHostelRenter;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Mpdf\Tag\U;

class SearchController extends BaseController
{
    //
    /**
     * @api {get} v2/search/hostel Tìm kiếm nhà trọ
     * @apiName /hostel
     * @apiGroup Search
     * @apiParam {String} province_id
     * @apiParam {String} district_id[]
     * @apiParam {String} ward_id
     * @apiParam {String} min_price
     * @apiParam {String} max_price
     * @apiParam {String} note
     * @apiParam {Number} type
     * @apiParam {Number} type_rent
     *
     * @apiDescription Api Tìm kiếm nhà trọ
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function search(Request $request)
    {
        $provinceId = $request->input('province_id');
        $districtId = $request->input('district_id');
        $wardId = $request->input('ward_id');
        $minPrice = $request->input('min_price');
        $maxPrice = $request->input('max_price');
        $type = $request->input('type');
        $typeRent = $request->input('type_rent');
        $note = $request->input('note');
        $properties = $request->all();

        if (!$request->has('type_rent')) {
            $typeRent = $type;
            $properties['type_rent'] = $type;
            $properties['type'] = null; // mặc định xếp vào là nhà trọ
            $type = null; // mặc định xếp vào là nhà trọ
        }

        if (empty($provinceId) || empty($districtId) || empty($minPrice) || empty($maxPrice) || ($type == -1)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $checkLimit = FindSession::query()
            ->where('user_id', $this->user->id)
            ->where('status', FindSession::SEARCHING)
            ->count();
        //	$checkLimit = 2;
        $limitSearch = config('constants.LIMIT_SEARCH');
        if ($checkLimit >= $limitSearch) {
            return response([
                'status' => 0,
                'message' => 'Bạn chỉ có tối đa ' . $limitSearch . ' lượt tìm kiếm hoạt động'
            ]);
        }

        $hostels = Hostel::query()
            ->when(!empty($provinceId), function ($q) use ($provinceId) {
                $q->where('province_id', $provinceId);
            })
            ->when(!empty($districtId), function ($q) use ($districtId) {
                $q->whereIn('district_id', $districtId);
            })
            ->when(!empty($wardId), function ($q) use ($wardId) {
                $q->where('ward_id', $wardId);
            })
//		                  ->when( ! empty( $minPrice ), function ( $q ) use ( $minPrice ) {
//			                  $q->where( 'smallest_price', '>=', $minPrice );
//		                  } )
//		                  ->when( ! empty( $maxPrice ), function ( $q ) use ( $maxPrice ) {
//			                  $q->where( 'greatest_price', '<=', $maxPrice );
//		                  } )
            ->when(!is_null($typeRent), function ($q) use ($typeRent) {
                $q->where('type_rent', $typeRent);
            })
            ->when(!is_null($type), function ($q) use ($type) {
                $q->where('type', $type);
            })->get();

        $ownerIds = $hostels->pluck('owner_id')->toArray();

        $ownersVip = User::query()
            ->whereIn('id', $ownerIds)
            ->whereHas('packageFindHostel', function ($q) {
                $q->where('package_id', 3);
            })
            ->get();

        $owners = User::query()->whereIn('id', $ownerIds)
            ->when(!empty($ownersVip->count()), function ($q) use ($ownersVip) {
                $q->whereNotIn('id', $ownersVip->pluck('id')->toArray());
            })
            ->get();

        $districtsName = null;
        $addressName = null;
        if (is_array($districtId)) {
            $districts = District::query()
                ->whereIn('districtid', $districtId)
                ->pluck('name')
                ->toArray();
            $districtsName = implode(', ', $districts);
        }
        $addressName = $districtsName . ' ' . Functions::getProvinceName($provinceId)->name;

        $findSession = FindSession::create([
            'user_id' => $this->user->id,
            'properties' => $properties,
            'status' => FindSession::SEARCHING,
            'note' => $note
        ]);

        SearchLog::create([
            'find_session_id' => $findSession->id,
            'properties' => $properties,
            'owner_ids' => $owners->pluck('id')->toArray()
        ]);
        // bắn cho chủ trọ
        \Notification::send($owners, new SearchHostel(
            $this->user,
            $districtsName,
            $findSession->id,
            $provinceId,
            $districtId
        ));

        \Notification::send($owners, new SearchHostelManageApp(
            $this->user,
            $districtsName,
            $findSession->id,
            $provinceId,
            $districtId
        ));

        if ($ownersVip->count() > 0) {
            $itroStaffs = User::query()->where('is_agent', true)
                ->when(!empty($districtId), function ($q) use ($districtId) {
                    $q->whereHas('agentDistricts', function ($q) use ($districtId) {
                        $q->whereIn('districtid', $districtId);
                    });
                })
                ->get();
            \Notification::send($itroStaffs, new SearchHostel(
                $this->user,
                $districtsName,
                $findSession->id,
                $provinceId,
                $districtId
            ));

            \Notification::send($itroStaffs, new SearchHostelManageApp(
                $this->user,
                $districtsName,
                $findSession->id,
                $provinceId,
                $districtId
            ));
        }

        //bắn cho nhân viên của từng nhà trọ
        foreach ($hostels as $hostel) {
            $staffs = $hostel->staffs;
            if (!empty($staffs)) {
                \Notification::send($staffs, new SearchHostel(
                    $this->user,
                    $districtsName,
                    $findSession->id,
                    $provinceId,
                    $districtId
                ));

                \Notification::send($staffs, new SearchHostelManageApp(
                    $this->user,
                    $districtsName,
                    $findSession->id,
                    $provinceId,
                    $districtId
                ));
            }
        }

        \Notification::send($this->user, new SearchHostelRenter(
            $findSession,
            $addressName
        ));

        return response([
            'status' => 1
        ]);
    }

    /**
     * @api {get} v2/search/province Cac tinh search chinh
     * @apiName /province
     * @apiGroup Search
     *
     * @apiDescription Api Cac tinh search chinh
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function getProvinceBestSearch(Request $request)
    {
        $items = Province::query()
            ->where('is_search', true)
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->provinceid,
                    'name' => $item->name,
                ];
            });
        return response([
            'status' => 1,
            'data' => $items
        ]);
    }

    /**
     * @api {get} v2/search/district Cac quan search chinh
     * @apiName /district
     * @apiGroup Search
     * * @apiParam {String} province_id
     * @apiDescription Api Cac quan search chinh
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function getDistrictBestSearch(Request $request)
    {
         $provinceId = $request->input('province_id');
         $districts = District::query()
                 ->withCount([
                     'findSessions'
                 ])
             ->where('provinceid', $provinceId)
             ->where('is_search', true)
             ->orderBy('find_sessions_count', 'desc')
             ->limit(6)
             ->get()
             ->map(function ($item) {
                 $arr = $item->toArray();
                 if(!empty($arr['image']))
                 {
                     $arr['image'] = '/files/'.$arr['image'];
                 }
                 return $arr;
             });
        return response([
            'status' => 1,
            'data' => $districts
        ]);
    }

    /**
     * @api {post} v2/search/update Cập nhật tìm kiếm
     * @apiName /update
     * @apiGroup Search
     * @apiParam {String} id id phiên tìm kiếm
     * @apiParam {String} province_id
     * @apiParam {String} district_id[]
     * @apiParam {String} ward_id
     * @apiParam {String} min_price
     * @apiParam {String} max_price
     * @apiParam {String} note
     * @apiParam {Number} type
     * @apiParam {Number} type_rent
     *
     * @apiDescription Api Cập nhật tìm kiếm
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function updateSearch(Request $request)
    {

        $provinceId = $request->input('province_id');
        $districtId = $request->input('district_id');
        $wardId = $request->input('ward_id');
        $minPrice = $request->input('min_price');
        $maxPrice = $request->input('max_price');
        $type = $request->input('type');
        $typeRent = $request->input('type_rent');
        $id = $request->input('id');
        $note = $request->input('note');
        $properties = $request->all();

        if (!$request->has('type_rent')) {
            $typeRent = $type;
            $properties['type_rent'] = $type;
            $properties['type'] = null; // mặc định xếp vào là nhà trọ
            $type = null; // mặc định xếp vào là nhà trọ

        }

        $findSession = FindSession::find($id);
        if (!$findSession) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        if (in_array($findSession->status, [FindSession::CANCEL, FindSession::FOUND])) {
            return response([
                'status' => 0,
                'message' => 'Phiên tìm kiếm đã hủy hoặc đã tìm thấy'
            ]);
        }

        if (empty($provinceId) || empty($districtId) || empty($minPrice) || empty($maxPrice) || ($type == -1)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $hostels = Hostel::query()
            ->when(!empty($provinceId), function ($q) use ($provinceId) {
                $q->where('province_id', $provinceId);
            })
            ->when(!empty($districtId), function ($q) use ($districtId) {
                $q->whereIn('district_id', $districtId);
            })
            ->when(!empty($wardId), function ($q) use ($wardId) {
                $q->where('ward_id', $wardId);
            })
//		                  ->when( ! empty( $minPrice ), function ( $q ) use ( $minPrice ) {
//			                  $q->where( 'smallest_price', '>=', $minPrice );
//		                  } )
//		                  ->when( ! empty( $maxPrice ), function ( $q ) use ( $maxPrice ) {
//			                  $q->where( 'greatest_price', '<=', $maxPrice );
//		                  } )
            ->when(!is_null($typeRent), function ($q) use ($typeRent) {
                $q->where('type_rent', $typeRent);
            })
            ->when(!is_null($type), function ($q) use ($type) {
                $q->where('type', $type);
            })
            ->get();

        $ownerIds = $hostels->pluck('owner_id')
            ->toArray();

        $owners = User::query()
            ->whereIn('id', $ownerIds)
            ->get();


        $logSent = SearchLog::query()
            ->where('find_session_id', $findSession->id)
            ->get();
        $ownerSent = [];
        foreach ($logSent as $log) {
            $ownerSent = array_merge($ownerSent, $log->owner_ids);
        }

        $findSession->update([
            'properties' => $properties,
            'note' => $note
        ]);

        SearchLog::create([
            'find_session_id' => $findSession->id,
            'properties' => $properties,
            'owner_ids' => $owners->pluck('id')->toArray()
        ]);

        if (!empty($ownerSent)) {
            $ownerToSend = User::query()
                ->whereNotIn('id', $ownerSent)
                ->whereIn('id', $ownerIds)
                ->get();
        } else {
            $ownerToSend = $owners;
        }

        $districtsName = null;
        $addressName = null;
        if (is_array($districtId)) {
            $districts = District::query()
                ->whereIn('districtid', $districtId)
                ->pluck('name')
                ->toArray();
            $districtsName = implode(', ', $districts);
        }

        $addressName = $districtsName . ' ' . Functions::getProvinceName($provinceId)->name;

        // bắn cho chủ trọ

        \Notification::send($ownerToSend, new SearchHostel(
            $this->user,
            $districtsName,
            $findSession->id,
            $provinceId,
            $districtId
        ));


        \Notification::send($ownerToSend, new SearchHostelManageApp(
            $this->user,
            $districtsName,
            $findSession->id,
            $provinceId,
            $districtId
        ));

        //bắn cho nhân viên của từng nhà trọ
        foreach ($hostels as $hostel) {
            $staffs = $hostel->staffs;
            if (!empty($staffs)) {
                \Notification::send($staffs, new SearchHostel(
                    $this->user,
                    $districtsName,
                    $findSession->id,
                    $provinceId,
                    $districtId
                ));

                \Notification::send($staffs, new SearchHostelManageApp(
                    $this->user,
                    $districtsName,
                    $findSession->id,
                    $provinceId,
                    $districtId
                ));
            }
        }


        \Notification::send($this->user, new SearchHostelRenter(
            $findSession,
            $addressName
        ));

        return response([
            'status' => 1
        ]);
    }

    /**
     * @api {post} v2/search/cancel Hủy phiên tìm kiếm
     * @apiName /cancel
     * @apiGroup Search
     * @apiParam {String} id
     *
     * @apiDescription Api Hủy phiên tìm kiếm
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function cancel(Request $request)
    {
        $id = $request->input('id');
        $item = FindSession::find($id);
        if (!$item) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $item->status = FindSession::CANCEL;
        $item->save();

        Conversation::query()
            ->where('find_session_id', $id)
            ->update([
                'status' => Conversation::ARCHIVED
            ]);

        DatabaseNotification::query()->where('find_session_id', $id)
            ->update([
                'status' => 2
            ]);


        return response([
            'status' => 1,
            'message' => 'Thành công'
        ]);
    }

    /**
     * @api {get} v2/search/customer Các phiên tìm kiếm phù hợp với chủ trọ
     * @apiName /customer
     * @apiGroup Search
     * @apiParam {String} hostel_id
     * @apiParam {String} limit
     * @apiParam {String} offset
     *
     * @apiDescription Api Các phiên tìm kiếm phù hợp với chủ trọ
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function customersRequest(Request $request)
    {
        $owner = $this->user;
        if ($this->user->type == User::STAFF) {
            $owner = $this->user->owner;
        }

        $limit = $request->input('limit', 10);
        $offset = $request->input('offset', 0);
        $hostelId = $request->input('hostel_id');
        $provinceId = $request->input('province_id');
        $districtId = $request->input('district_id');
        $hostels = Hostel::query()
            ->where('owner_id', $owner->id);
        $phoneVip = config('constants.PHONE_VIP_3');
        if (in_array($this->user->phone, $phoneVip)) {
            $owners = UserPackageFindHostel::query()
                ->where('package_id', 3)
                ->pluck('user_id')
                ->toArray();
            if (!empty($owners)) {
                $hostels = Hostel::query()
                    ->whereIn('owner_id', $owners);
            }
        }
        $hostels = $hostels->when(!empty($hostelId), function ($q) use ($hostelId) {
            $q->where('id', $hostelId);
        })->when(!empty($provinceId), function ($q) use ($provinceId) {
            $q->where('province_id', $provinceId);
        })->when(!empty($districtId), function ($q) use ($districtId) {
            $q->whereIn('district_id', $districtId);
        });


        $hostelDistrict = clone $hostels;
        $hostels = $hostels->get();
        $districtArrs = $hostelDistrict->whereNotNull('district_id')
            ->pluck('name', 'district_id')
            ->unique()
            ->toArray();

        //dd($hostels->pluck('id')->toArray());
        $price = Functions::getPriceHostelArr($hostels->pluck('id')->toArray());
        $minPrice = null;
        $maxPrice = null;
        if (isset($price['min_price'])) {
            $minPrice = $price['min_price'];
        }

        if (isset($price['max_price'])) {
            $maxPrice = $price['max_price'];
        }

        $sessionAlready = Conversation::query()
            ->whereHas('users', function ($q) use ($owner) {
                $q->where('users.id', $owner->id);
            })
            ->pluck('find_session_id')
            ->filter(function ($value) {
                return !is_null($value);
            })
            ->unique()
            ->toArray();

        //dd($sessionAlready);

        $excludeLeads = \DB::table('exclude_leads')
            ->where('user_id', $owner->id)
            ->pluck('find_session_id')
            ->toArray();

        $leadTaken = LeadUserTake::query()->where('user_id', $owner->id)
            ->pluck('find_session_id')
            ->toArray();


        $types = $hostels->pluck('type_rent')->unique()->toArray();

       // dd($districtArrs);
        $items = FindSession::query()
            ->where(function ($q) use ($hostels) {
                foreach ($hostels as $hostel) {
                    $districtId = $hostel->district_id;
                    $minPrice = $hostel->min_price;
                    $maxPrice = $hostel->max_price;
                    $q->orWhere(function ($q) use ($districtId, $minPrice, $maxPrice) {
                        $q->whereHas('districts', function ($q) use ($districtId) {
                            $q->where('find_session_districts.district_id', $districtId);

                        });

                        $q->where(function ($q) use ($maxPrice, $minPrice) {
                            $q->when(!is_null($minPrice), function ($q) use ($minPrice) {
                                $q->orwhere('min_price', '<=', $minPrice);
                            });
                            $q->when(!is_null($maxPrice), function ($q) use ($maxPrice) {
                                $q->orwhere('max_price', '>=', $maxPrice);
                            });
                        });


                    });
                }
            })

//		                    ->whereHas( 'districts', function ( $q ) use ( $districtArrs ) {
//			                    $q->whereIn( 'find_session_districts.district_id', $districtArrs );
//
//		                    } )
//		                    ->when( ! is_null( $minPrice ), function ( $q ) use ( $minPrice ) {
//			                    $q->where( 'min_price', '>=', $minPrice );
//		                    } )
//		                    ->when( ! is_null( $maxPrice ), function ( $q ) use ( $maxPrice ) {
//			                    $q->where( 'max_price', '<=', $maxPrice );
//		                    } )
            ->when(!empty($excludeLeads), function ($q) use ($excludeLeads) {
                $q->whereNotIn('id', $excludeLeads);
            })
            ->when(!empty($leadTaken), function ($q) use ($leadTaken) {
                $q->whereNotIn('id', $leadTaken);
            })
            ->with('lead')
            ->whereNotIn('id', $sessionAlready)
            ->where('status', FindSession::SEARCHING)
            ->whereIn('type_rent', $types)
            ->limit($limit)
            ->with('hostelType')
            ->offset($offset)
            ->orderBy('id', 'desc')
            ->get()
            ->map(function ($item) {
                //	id, province, district, min_price, max_price, status
                $user = $item->user;
                $properties = $item->properties;
                $districtArr = [];
                if (isset($properties['district_id'])) {
                    foreach ($properties['district_id'] as $districtId) {
                        $districtArr[] = [
                            'districtid' => $districtId,
                            'name' => Functions::getDistrictName($districtId)->name
                        ];
                    }
                }

                $hostelType = null;
                if ($item->hostelType) {
                    $hostelType = [
                        'id' => $item->hostelType->id,
                        'name' => $item->hostelType->name
                    ];
                }
                $renter = null;
                $leadArr = null;
                if (empty($item->lead_id)) {
                    $renter = [
                        'id' => $user->id,
                        'name' => $user->name_text,
                        'phone' => $user->phone,
                        'image' => $user->image
                    ];
                } else {
                    $lead = $item->lead;
                    if ($lead) {
                        $leadArr = [
                            'name' => $lead->name,
                            'phone' => $lead->phone,
                            'source' => $lead->source,
                            'link' => $lead->source_link,
                            'content' => $lead->note
                        ];
                    }
                }

                $typeRent = null;
                if (isset($properties['type_rent'])) {
                    $typeRent = $properties['type_rent'];
                } else if (isset($properties['type'])) {
                    $typeRent = $properties['type'];
                }

                return [
                    'id' => $item->id,
                    'renter' => $renter,
                    'province' => [
                        'provinceid' => isset($properties['province_id']) ? $properties['province_id'] : null,
                        'name' => isset($properties['province_id']) ? Functions::getProvinceName($properties['province_id'])->name : null,
                    ],
                    'district' => $districtArr,
                    'min_price' => isset($properties['min_price']) ? $properties['min_price'] : null,
                    'max_price' => isset($properties['max_price']) ? $properties['max_price'] : null,
                    'status' => $item->status,
                    'created_at' => $item->created_at->format('d/m/Y H:i'),
                    'num_of_conversation' => $item->conversations->count(),
                    'type' => $typeRent,
                    'note' => $item->note,
                    'hostel_type' => $hostelType,
                    'lead' => $leadArr,
                    'is_lead' => empty($item->lead_id) ? false : true
                ];
            });

        return response([
            'status' => 1,
            'data' => $items
        ]);
    }
}
