<?php

namespace App\Console\Commands\PropertyReviewService;


use App\Exceptions\ApiErrorException;
use App\Models\PropertyReview;
use App\Models\PropertyReviewCategory;
use App\Models\PropertyReviewCategoryMapping;
use App\Models\PropertyReviewKeywordMapping;
use Carbon\Carbon;
use Google\Protobuf\Api;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Http\Request;
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 PropertyReviewAnalyzeService extends Command
{
    protected $signature = 'cron:property-review-analyze-service {review_id}';

    protected $description = '';


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

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

    }

    protected function requestService($params = [])
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];

        try {

            $client = new \GuzzleHttp\Client([
                    'max' => 5,
                    'strict' => false,
                    'referer' => false,
                    'protocols' => ['https'],
                    'timeout' => 30,
                    'headers' => [
                        'Authorization' => 'Bearer ' . config('app.openAISecretKey'),
                        'Content-Type' => 'application/json',
                        'Cache-Control' => 'no-cache',
                        'Connection' => 'keep-alive',
                        'Accept-Encoding' => 'gzip'
                    ]
                ]
            );


            $result = $client->post('https://api.openai.com/v1/chat/completions', [
                'body' => json_encode($params['query'])
            ]);

            $result = $result->getBody()->getContents();
            $result = json_decode($result, 1);

            $choiceMessage = reset($result['choices']);

            if (isset($choiceMessage['message']['content'])) {
                $choiceMessage = json_decode($choiceMessage['message']['content'], 1);
                $data = $choiceMessage;
            }

            $response = [
                'status' => true,
                'data' => $data,
            ];


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }

        return $response;

    }

    public function handle()
    {

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


        //420

        $propertyReview = PropertyReview::where('id', $this->argument('review_id'))
            ->with('channel')
            ->with('property')
            ->first();

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

        if (!$propertyReview) {
            Log::error('Property Review: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
            return false;
        }


        $propertyReviewCategory = PropertyReviewCategory::where('status', 1)->select(['id', 'name'])->get()->toArray();
        $propertyReviewCategoryText = implode(', ', collect($propertyReviewCategory)->pluck('name')->toArray());


        $params['query'] = [
            'model' => 'gpt-4o',
            'response_format' => [
                'type' => 'json_object'
            ],
            'messages' => [
                [
                    'role' => 'system',
                    'content' => 'Sen bir otel gelir yönetimi uzmanısın ve otellere yapılan yorumları değerlendiriyosun. Cevaplar SADECE JSON formatında. Yorumu genel olarak değerlendirip, misafir gibi düşünüp 0: olumsuz,1: olumlu olacak şekilde sentiment alanında işaretleyelim. Gelen yorumları \"' . $propertyReviewCategoryText . '\" kategorilerine göre categories alanında işaretleyip gruplayalım. Her bir gruplanan kategori için de 0: olumsuz,1: olumlu olacak şekilde işaretleyelim, ilgisiz kategorileri eklemeyelim. keywords alanında bu yorum ile ilgili kilit kelimeleri, ileride kelime bulutu yapmak için ingilizce çıkaralım,kelimeler otel ve otelcilik ile ilgili olsun, kelimeler normal metin şeklinde, aralıkları boşluklu ve sadece ilk harfleri büyük olsun, bu kelimeler için de 0: olumsuz,1: olumlu olacak şekilde işaretleyelim. Yorumu da language parametresi altında 2 haneli ISO koduna göre verelim.'
                ],
                [
                    'role' => 'user',
                    'content' => $propertyReview['review']
                ]
            ]

        ];

        $propertyReviewAnalyze = $this->requestService($params);
        //$propertyReviewAnalyze = json_decode('{"status":true,"data":{"sentiment":0,"categories":{"Location":0,"Breakfast":0,"Service":1,"Cleanliness":1,"Room Facilities":0},"keywords":{"Location":0,"Breakfast":0,"Service Quality":1,"Cleaning":1,"Room Amenities":0}}}', 1);

        if ($propertyReviewAnalyze['status']) {


            DB::beginTransaction();

            $transactionSave = false;

            try {


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

                PropertyReview::where('id', $propertyReview['id'])->update(['sentiment' => $propertyReviewAnalyze['data']['sentiment'], 'language' => $propertyReviewAnalyze['data']['language']]);

                //PropertyReviewCategoryMapping
                $this->info(date('Y-m-d H:i:s') . ': Property Review Category Mapping: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
                $bulkReviewCategoryMapping = [];
                PropertyReviewCategoryMapping::where('review_id', $propertyReview['id'])->delete();
                foreach ($propertyReviewAnalyze['data']['categories'] as $category => $categorySentiment) {

                    $categorySelected = collect($propertyReviewCategory)->where('name', $category)->first();

                    if (isset($categorySelected['id'])) {

                        $bulkReviewCategoryMapping[] = [
                            'review_id' => $propertyReview['id'],
                            'property_id' => $propertyReview['property_id'],
                            'channel_id' => $propertyReview['channel_id'],
                            'category_id' => $categorySelected['id'],
                            'sentiment' => $categorySentiment,
                            'review_date' => $propertyReview['review_date'],
                            'status' => 1,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];

                    }
                }

                if (!empty($bulkReviewCategoryMapping)) {
                    PropertyReviewCategoryMapping::insert($bulkReviewCategoryMapping);
                }
                //PropertyReviewCategoryMapping


                //PropertyReviewKeywordMapping
                if (is_array($propertyReviewAnalyze['data']['keywords'])) {
                    $this->info(date('Y-m-d H:i:s') . ': Property Review Keyword Mapping: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
                    $bulkReviewKeywordMapping = [];
                    PropertyReviewKeywordMapping::where('review_id', $propertyReview['id'])->delete();
                    foreach ($propertyReviewAnalyze['data']['keywords'] as $keyword => $keywordSentiment) {

                        $bulkReviewKeywordMapping[] = [
                            'review_id' => $propertyReview['id'],
                            'property_id' => $propertyReview['property_id'],
                            'channel_id' => $propertyReview['channel_id'],
                            'keyword' => $keyword,
                            'sentiment' => $keywordSentiment,
                            'review_date' => $propertyReview['review_date'],
                            'status' => 1,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];

                    }

                    if (!empty($bulkReviewKeywordMapping)) {
                        PropertyReviewKeywordMapping::insert($bulkReviewKeywordMapping);
                    }
                }
                //PropertyReviewKeywordMapping


                //throw new Exception('Booking Room could not be made');

                $transactionSave = true;


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

            if ($transactionSave) {
                DB::commit();
            } else {
                DB::rollBack();
            }
        }


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


    }
}
