<?php

namespace App\Services\Repositories;

use App\Models\Reservation;
use App\Models\ReservationPayment;
use App\Models\Room;
use App\Models\Order;
use App\Models\Cobon;
use App\Services\Interfaces\ReservationRepositoryInterface;
use App\Services\Payment\MyFatoorahPayment;
use App\Services\Payment\PaymentService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class ReservationRepository implements ReservationRepositoryInterface
{
    public function get(Request $request)
    {
        $query = Reservation::orderBy('id', 'DESC');

        if ($request->phone) 
        {
            $query->whereHas('user', function ($q) use($request)
            {
                $q->where('phone', $request->phone);
            });
        }

        if ($request->user_id) {
            $query->where('user_id', $request->user_id);
        }
        
        if ($request->id) {
            $query->where('id', $request->id);
        }

        if ($request->room) {
            $query->whereHas('room.currentDescription', function ($q) use($request){
                $q->where('name','LIKE','%'.$request->room.'%');
            });
        }

        if ($request->date) {
            $query->whereDate('date', $request->date);
        }

        if ($request->time) {
            $query->where('start_time','<=',$request->time)->where('end_time','>=',$request->time);
        }

        if ($request->count_members) {
            $query->where('count_members', $request->count_members);
        }

        if ($request->length_time) {
            $query->where('length_time', $request->length_time);
        }

        if ($request->date_from) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->date_to) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }


        if ( !is_null($request->status) && $request->status == 0) {
            $query->onlyTrashed();
        }

        if ($request->paginate ?? null) {
            $clients= $query->paginate(50);
        }else{
            $clients=$query->cursor();
        }

        return $clients;
    }

    //
    public function save(Request $request, ?Reservation $review): Reservation
    {
        $data= $request->all();
        unset($data['id']);// for security reasons

        if (!$review) {
            $review = Reservation::create($data);
        } else {
            $review->update($data);
            ReservationPayment::where('review_id', $review->id)->delete();
        }
        $this->saveData( $request, $review->id );
        return $review;
    }

    private function saveData(Request $request, int $review_id ) :void
    {
        $requestData= $request->all();
        foreach (languages() as $lang) {
            $data=[
                'review_id'=> $review_id,
                'language_id'=> $lang->id,
                'name'=> $requestData['name_'.$lang->local],
                'description'=> $requestData['description_'.$lang->local],
            ];

            ReservationPayment::create($data);
        }
    }
    /**
     * Remove the specified client from storage.
     * @param Request $request
     * @param int $id
     * @return array
     * @throws Exception
     */
    public function destroy(Request $request, int $id) :array
    {
        $client= Reservation::withTrashed()->find($id);
        if ($client) {
            if ($client->deleted_at) {
                $client->forceDelete();
            } else {
                $client->delete();
            }
            return [ ['message'=> __('dashboard.deletedDone')]];
        } else{
            return [ ['message'=> __('dashboard.noResult')], 400];
        }
    }

    /**
     * Remove several clients by IDs.
     *
     * @param Request $request
     * @return array
     */
    public function destroyAll(Request $request) :array
    {
        $ids= $request->ids;
        $query= Reservation::whereIn('id', $ids);
        if ($request->force) {
            $deleted= $query->onlyTrashed()->forceDelete();
        } else {
            $deleted= $query->delete();
        }
        if($deleted){
            return [['message'=> __('dashboard.deletedDone')]];
        }
        return [ ['message'=> __('dashboard.noResult')], 400];
    }

    /**
     * Restore the specified client from storage.
     *
     * @param Request $request
     * @param int $id
     * @return array
     */
    public function restore(Request $request, int $id) :array
    {
        $client= Reservation::withTrashed()->find($id);
        if ($client) {
            $client->restore();
            return [['message'=> __('dashboard.saveDone')]];
        }
        return [['message'=> __('dashboard.noResult')], 400];

    }

    /**
     * Restore several clients by IDs.
     *
     * @param Request $request
     * @return array
     */
    public function restoreAll(Request $request) :array
    {
        $ids= $request->ids;
        Reservation::whereIn('id', $ids)->onlyTrashed()->restore();
        return [['message'=> __('dashboard.saveDone')]];
    }
    public function orderReservation(Request $request)
    {
        $room = Room::findOrFail($request->room_id);
        $reservation = $this->saveReservation($request,$room);
        Session::put(['reservation_id'=>$reservation->id]);
        $response =
        [
            'status' => 200,
            'message' => __('web.success'),
            'data' => route('cart.index')
        ];
        return $response;
    }
    public function pay(Request $request)
    {
        $room = Room::findOrFail($request->room_id);
        $my_fatoorah_payment = new MyFatoorahPayment();
        $payment = new PaymentService($my_fatoorah_payment);
        $reservation = $this->saveReservation($request,$room);
        
        
        
        $content =
            [
                'id'=>$reservation->id,
                'type'=>'reservation',
                'total'=>$reservation->payment->total,
                'token'=>$reservation->token,
                'url'=>$request->url,
                'status'=>__('web.reservation'),
                'payment_status'=>route('web.reservation.status'),
            ];
        if($reservation->payment->total > 0)
        {
            $response = $payment->payment($content);
        }
        else
        {
            $response =
            [
                'status' => 200,
                'data' => route('web.profile'),
                'message' => __('web.success'),
            ];
        }
        return $response;
    }
    private function saveReservation(Request $request,$room)
    {
        $token = bcrypt(rand(11111,99999).time());
        $times = explode('/',$request->time);
        $start_time=date('H:i:s',strtotime($times[0]));
        $end_time=date('H:i:s',strtotime($times[1]));
        
        $date1= date_create($times[0]);
        $date2=date_create($times[1]);

        if($end_time > $start_time)
        {
            $diff=date_diff($date2,$date1);
            $hours =  $diff->h;
        }
        else
        {
            $end = date_create($end_time);
            $midnight = date_create(date('00:00:00'));
            $end_times = date_diff($end,$midnight);
            $end_hours =  $end_times->h;
            $start = date_create($start_time);
            $start_times = date_diff($midnight,$start);
            $start_hours =  $start_time < "12:00:00" ? $start_times->h : 24 - $start_times->h;
            $hours = $end_hours + $start_hours;
        }
        
        $duration = $hours;
        $request->merge(['start_time'=>$start_time,'end_time'=>$end_time,'room'=>$room]);
        $response = $this->calculate($request);
        // $total = $request->capacity * $room->cost * $duration;
        
        $reservation = Reservation::create([
            'token'=>$token,
            'date'=>$request->date,
            'start_time'=>$start_time,
            'end_time'=>$end_time,
            'length_time'=>$duration,
            'count_members'=>$request->capacity,
            'user_id'=>Auth::user()->id,
            'room_id'=>$request->room_id
        ]);
        ReservationPayment::create([
            'reservation_id'=>$reservation->id,
            'room_cost'=>$response['total_reservation'],
            'tax'=>$response['tax'],
            'cobon_id'=>$response['cobon_id'],
            'discount'=>$response['discount'],
            'total'=>$response['total'],
        ]);
        if($response['total'] > 0)
        {
            $reservation->delete();
        }
        return $reservation;
    }
    
    public function calculate($request)
    {
        $times = explode('/',$request->time);
        $start_time=date('H:i:s',strtotime($request->start_time));
        $end_time=date('H:i:s',strtotime($request->end_time));
        
        $date1= date_create($start_time);
        $date2=date_create($end_time);

        if($end_time > $start_time)
        {
            $diff=date_diff($date2,$date1);
            $hours =  $diff->h;
        }
        else
        {
            $end = date_create($end_time);
            $midnight = date_create(date('00:00:00'));
            $end_times = date_diff($end,$midnight);
            $end_hours =  $end_times->h;
            $start = date_create($start_time);
            $start_times = date_diff($midnight,$start);
            $start_hours =  $start_time < "12:00:00" ? $start_times->h : 24 - $start_times->h;
            $hours = $end_hours + $start_hours;
        }
        $cobon_id = null;
        $cobon = $request->cobon;
        $discount = 0;
        $cobon_msg = '';
        $duration = $hours;
        $total = $request->capacity * $request->room->cost * $duration;
        $total_reservation = 0;
        $total_reservation += getAmountDetails($total)['amount'];
        
        if ($request->cobon)
        {
            $cobon_id = null;
            // $cobon = (new CobonRepository())->get($request)->first();
            $cobon = Cobon::where('code',$request->cobon)->first();
            if($cobon)
            {
                $request->merge(['cobon_id'=>$cobon->id]);
                // $count = (new OrderRepository())->get($request)->count();
                $count  = Order::whereHas('payment', function($q) use($cobon_id){
                    $q->where('cobon_id', $cobon_id);
                })->count();

                if($cobon->count_user >= $count)
                {
                    if($cobon->discount_type == 'percentage')
                    {
                        // $discount = $total * ($cobon->discount / 100) ;
                        $discount = $total_reservation * ($cobon->discount / 100) ; //NEWLY_ADDED
                    }
                    else
                    {
                        $discount = $cobon->discount;
                    }
                    $cobon_id = $cobon->id;
                    $cobon_msg = __('web.valid_cobon') .' : '.$discount .' '.__('web.sar');
                }
                else
                {
                    $cobon_msg = __('web.not_valid_cobon');
                }
            }
            else
            {
                $cobon_msg = __('web.not_valid_cobon');
            }
        }
        $tax = ($total_reservation - $discount) * (settings('tax') / 100) ;
        
        return [
            'total_reservation' => round($total_reservation,2),
            'discount' => $discount,
            'cobon' => $cobon,
            'cobon_id' => $cobon_id,
            'cobon_msg' => $cobon_msg,
            'tax' => round($tax,2),
            'total' => round($total_reservation + $tax - $discount ,2),
        ];
    }
}
