<?php

namespace App\Console\Commands\PropertyReviewService;


use App\Exceptions\ApiErrorException;
use App\Jobs\PropertyReviewAnalyzeServiceJob;
use App\Jobs\PropertyReviewServiceJob;
use App\Models\PropertyReview;
use App\Models\PropertyReviewChannelMapping;
use Carbon\Carbon;
use Google\Protobuf\Api;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Exception;

class PropertyReviewService extends Command
{
    protected $signature = 'cron:property-review-service {property_id} {channel_id}';

    protected $description = '';

    protected $maxPageSize = 10;

    protected $xApiKey = 'sk_live_995958e62147c2ae81f6be573daa7c0d0bcedf550ff5dae52315bd05f1272803';


    public function __construct()
    {
        parent::__construct();

        $this->restClient = new Client(['http_errors' => false]);

    }

    protected function requestService($params)
    {

        try {

            $requestUrl = $params['requestUrl'];
            $requestParams['headers']['x-api-key'] = $this->xApiKey;
            $requestParams['headers']['Content-Type'] = 'application/json';

            unset($params['requestUrl']);
            $requestParams['query'] = $params;

            $result = $this->restClient->request('GET', $requestUrl, $requestParams);

            $getResponseBody = $result->getBody()->getContents();
            $getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];

            //$getResponseData = json_decode(file_get_contents(storage_path() . '/response.json'), 1);
            //$getResponseData = json_decode(file_get_contents(storage_path() . '/google.json'), 1);
            //$getResponseData = json_decode(file_get_contents(storage_path() . '/Tripadvisor.json'), 1);
            //$getResponseData = json_decode(file_get_contents(storage_path() . '/Tripadvisor.json'), 1);

            if (isset($getResponseData['error'])) {
                throw new ApiErrorException($getResponseData['detail']);
            }

            $response['status'] = true;
            $response['data'] = $getResponseData;

        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::debug($message);
            $response['message'] = $e->getMessage();

            dd($response);

        }

        return $response;

    }

    public function handle()
    {

        $this->info(date('Y-m-d H:i:s') . ' START');

        $propertyReviewChannelMapping = PropertyReviewChannelMapping::where('property_id', $this->argument('property_id'))
            ->where('channel_id', $this->argument('channel_id'))
            ->with('channel')
            ->with('property')
            ->first();

        $propertyReviewChannelMapping = $propertyReviewChannelMapping ? $propertyReviewChannelMapping->toArray() : null;

        Log::debug('Property Review: ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

        switch ($propertyReviewChannelMapping['channel_id']) {

            //BookingCom
            case '1':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {


                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/booking/hotel/reviews',
                        'hotel_id' => $propertyReviewChannelMapping['parameterArray']['hotelId'],
                        'sort' => 'newest',
                        'per_page' => 20,
                        'page' => ($i + 1)
                    ];

                    $requestReview = $this->requestService($requestParams);

                    //$bulkReview = [];
                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['data']['reviews'] as $review) {

                            try {

                                if (empty($review['review']['positive']) && empty($review['review']['negative'])) {
                                    continue;
                                }

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['id'],
                                    'author' => $review['guest']['name'],
                                    'title' => fillOnUndefined($review['review'], 'title'),
                                    'review' => $review['review']['positive'] . ' ' . $review['review']['negative'],
                                    'review_date' => Carbon::parse($review['reviewed_date'])->toDateTimeString(),
                                    'rating' => $review['score'],
                                    'top_rating' => 10,
                                    'score' => number_format($review['score'] / 10 * 100, 2),
                                    'language' => $review['review']['language'],
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];

                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //Google
            case '2':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;
                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/google_reviews/reviews-paginated',
                        'data_id' => $propertyReviewChannelMapping['parameterArray']['dataId'],
                        'sort_by' => 'newest',
                        'pages' => 10
                    ];

                    $requestReview = $this->requestService($requestParams);


                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['reviews'] as $review) {

                            if (empty($review['text'])) {
                                continue;
                            }

                            try {

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['review_id'],
                                    'author' => $review['reviewer']['name'],
                                    'title' => null,
                                    'review' => $review['text'],
                                    'review_date' => Carbon::parse($review['iso_date'])->toDateTimeString(),
                                    'rating' => $review['rating'],
                                    'top_rating' => 5,
                                    'score' => number_format($review['rating'] / 5 * 100, 2),
                                    'language' => null,
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];

                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //Tripadvisor
            case '3':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/tripadvisor/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
                        'per_page' => 20,
                        'page' => ($i + 1)
                    ];

                    $requestReview = $this->requestService($requestParams);

                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['reviews'] as $review) {

                            if (!fillOnUndefined($review, 'text')) {
                                continue;
                            }

                            try {

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['id'],
                                    'author' => $review['user']['display_name'],
                                    'title' => fillOnUndefined($review, 'title'),
                                    'review' => fillOnUndefined($review, 'text'),
                                    'review_date' => Carbon::parse($review['created_date'])->toDateTimeString(),
                                    'rating' => $review['rating'],
                                    'top_rating' => 5,
                                    'score' => number_format($review['rating'] / 5 * 100, 2),
                                    'language' => fillOnUndefined($review, 'language'),
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];

                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //Agoda
            case '4':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/agoda/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
                        'page' => ($i + 1)
                    ];

                    $requestReview = $this->requestService($requestParams);


                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['reviews'] as $review) {

                            if (!fillOnUndefined($review, 'comment')) {
                                continue;
                            }

                            try {

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['review_id'],
                                    'author' => null,
                                    'title' => fillOnUndefined($review, 'title'),
                                    'review' => fillOnUndefined($review, 'comment'),
                                    'review_date' => Carbon::parse($review['date'])->toDateTimeString(),
                                    'rating' => $review['rating'],
                                    'top_rating' => 10,
                                    'score' => number_format($review['rating'] / 10 * 100, 2),
                                    'language' => fillOnUndefined($review, 'language'),
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];

                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //Trip.com
            case '5':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/tripcom/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
                        'page' => ($i + 1),
                        'page_size' => 50
                    ];

                    $requestReview = $this->requestService($requestParams);

                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['data']['reviews'] as $review) {

                            if (!fillOnUndefined($review, 'text')) {
                                continue;
                            }

                           /* if ($review['source'] != 1) {
                                continue;
                            }*/

                            try {

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['id'],
                                    'author' => isset($review['reviewer_name']) ? $review['reviewer_name'] : null,
                                    'title' => fillOnUndefined($review, 'title'),
                                    'review' => fillOnUndefined($review, 'text'),
                                    'review_date' => Carbon::parse($review['date'])->toDateTimeString(),
                                    'rating' => $review['rating'],
                                    'top_rating' => 10,
                                    'score' => number_format($review['rating'] / 10 * 100, 2),
                                    'language' => fillOnUndefined($review, 'language'),
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];


                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //Expedia.com
            case '6':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $requestParams = [
                        'requestUrl' => 'https://api.stayapi.com/v1/expedia/hotel/reviews',
                        'property_id' => $propertyReviewChannelMapping['parameterArray']['hotelId'],
                        'page' => $i,
                        'page_size' => 5
                    ];

                    $requestReview = $this->requestService($requestParams);

                    if ($requestReview['status']) {

                        foreach ($requestReview['data']['reviews'] as $review) {

                            if (!fillOnUndefined($review, 'text')) {
                                continue;
                            }

                            try {

                                preg_match('/(\d+)\s*\/\s*(\d+)/', $review['rating'], $matches);

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => $review['id'],
                                    'author' => isset($review['reviewer_name']) ? $review['reviewer_name'] : null,
                                    'title' => fillOnUndefined($review, 'title'),
                                    'review' => fillOnUndefined($review, 'text'),
                                    'review_date' => Carbon::parse($review['review_date'])->toDateTimeString(),
                                    'rating' => (int)$matches[1],
                                    'top_rating' => 10,
                                    'score' => number_format((int)$matches[1] / 10 * 100, 2),
                                    'language' => fillOnUndefined($review, 'language'),
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];


                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;

            //HolidayCheck
            case '7':

                $this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);

                $maxPageSize = 1;

                if ($propertyReviewChannelMapping['fetch_status'] == 3) {
                    $maxPageSize = $this->maxPageSize;
                    PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
                }


                for ($i = 0; $i < $maxPageSize; $i++) {

                    $hotelId = $propertyReviewChannelMapping['parameterArray']['hotelId'];
                    $limit = 10;
                    $offset = $i * $limit;

                    $requestParams = [
                        'requestUrl' => "https://www.holidaycheck.de/api/hotel-reviews;filter=hotel.id:{$hotelId};limit={$limit};offset={$offset};select=id,user,title,texts,textAdvice,hotel,travelDate,recommendation,ratings,ranking,proofedReservation,ownerComment,additional,entryDate;sort=entryDate:desc",
                    ];

                    $requestReview = $this->requestService($requestParams);

                    if ($requestReview['status']) {

                        $reviews = isset($requestReview['data']['data']['items']) ? $requestReview['data']['data']['items'] : [];

                        foreach ($reviews as $review) {

                            $reviewText = fillOnUndefined($review, 'textAdvice');
                            if (empty($reviewText)) {
                                $reviewText = fillOnUndefined($review, 'texts.GENERAL');
                            }

                            if (empty($reviewText)) {
                                continue;
                            }

                            try {

                                $rating = fillOnUndefined($review, 'ratings.GENERAL.GENERAL');

                                $author = fillOnUndefined($review, 'user.firstName');
                                if (empty($author)) {
                                    $author = fillOnUndefined($review, 'user.name');
                                }

                                $bulkReview = [
                                    'property_id' => $propertyReviewChannelMapping['property_id'],
                                    'channel_id' => $propertyReviewChannelMapping['channel_id'],
                                    'channel_review_id' => fillOnUndefined($review, 'id'),
                                    'author' => $author,
                                    'title' => fillOnUndefined($review, 'title'),
                                    'review' => $reviewText,
                                    'review_date' => Carbon::createFromTimestampMs(fillOnUndefined($review, 'entryDate'))->toDateTimeString(),
                                    'rating' => $rating,
                                    'top_rating' => 6,
                                    'score' => number_format($rating / 6 * 100, 2),
                                    'language' => fillOnUndefined($review, 'originalLocale'),
                                    'detail' => json_encode($review),
                                    'status' => 1,
                                    'created_at' => time(),
                                    'updated_at' => time(),
                                ];

                                $propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
                                    ->where('channel_id', $bulkReview['channel_id'])
                                    ->where('channel_review_id', $bulkReview['channel_review_id'])
                                    ->first();

                                if (!$propertyReviewCheck) {
                                    $propertyReviewCreate = PropertyReview::create($bulkReview);

                                    dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));

                                    $this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                } else {
                                    $this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
                                }


                            } catch (Exception $e) {
                                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                                Log::error($message);

                                //dd($message);
                            }

                        }

                    }


                }


                PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);

                break;
        }


        $this->info(date('Y-m-d H:i:s') . ' FINISHED');


    }
}
