<?php


namespace App\Core\Service;

use App\Core\Repository\Language\LanguageRepository;
use App\Core\Repository\LanguageBase\LanguageBaseRepository;
use App\Core\Repository\LanguageTranslate\LanguageTranslateRepository;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Str;


class LanguageBaseService
{
    private $languageRepository;
    private $languageBaseRepository;
    private $languageTranslateRepository;
    private $request;
    private $tableVariables;


    public function __construct
    (
        Request $request,
        LanguageBaseRepository $languageBaseRepository,
        LanguageTranslateRepository $languageTranslateRepository,
        LanguageRepository $languageRepository
    )
    {
        $this->request = $request;
        $this->languageBaseRepository = $languageBaseRepository;
        $this->languageTranslateRepository = $languageTranslateRepository;
        $this->languageRepository = $languageRepository;

        $this->tableVariables = [

/*            'currency' => [
                'repository' => 'App\Core\Repository\Currency\CurrencyRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'language' => [
                'repository' => 'App\Core\Repository\Language\LanguageRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_channel_category' => [
                'repository' => 'App\Core\Repository\PropertyChannelCategory\PropertyChannelCategoryRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_content_category' => [
                'repository' => 'App\Core\Repository\PropertyContentCategory\PropertyContentCategoryRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_executive_type' => [
                'repository' => 'App\Core\Repository\PropertyExecutiveType\PropertyExecutiveTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_fact' => [
                'repository' => 'App\Core\Repository\PropertyFact\PropertyFactRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => true,
                'parent_column_name' => 'parent_id'
            ],

            'property_photo_category' => [
                'repository' => 'App\Core\Repository\PropertyPhotoCategory\PropertyPhotoCategoryRepository',
                'source_column' => 'category_name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => 'null'
            ],

            'property_room_bed_type' => [
                'repository' => 'App\Core\Repository\PropertyRoomBedType\PropertyRoomBedTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => 'null'
            ],

            'property_room_type' => [
                'repository' => 'App\Core\Repository\PropertyRoomType\PropertyRoomTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => 'null'
            ],

            'property_type' => [
                'repository' => 'App\Core\Repository\PropertyType\PropertyTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => 'null'
            ],

            'country' => [
                'repository' => 'App\Core\Repository\Country\CountryRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_room_view_type' => [
                'repository' => 'App\Core\Repository\PropertyRoomViewType\PropertyRoomViewTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_booking_type' => [
                'repository' => 'App\Core\Repository\PropertyBookingType\PropertyBookingTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_booking_payment_type' => [
                'repository' => 'App\Core\Repository\PropertyBookingPaymentType\PropertyBookingPaymentTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_availability_type' => [
                'repository' => 'App\Core\Repository\PropertyAvailabilityType\PropertyAvailabilityTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_place_category' => [
                'repository' => 'App\Core\Repository\PropertyPlaceCategory\PropertyPlaceCategoryRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => true,
                'parent_column_name' => 'parent_id'
            ],
            'property_place_working_hour' => [
                'repository' => 'App\Core\Repository\PropertyPlaceWorkingHour\PropertyPlaceWorkingHourRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => 'parent_id'
            ],


            'property_place_fact_title' => [
                'repository' => 'App\Core\Repository\PropertyPlaceFactTitle\PropertyPlaceFactTitleRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'property_place_fact' => [
                'repository' => 'App\Core\Repository\PropertyPlaceFact\PropertyPlaceFactRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'place_category_field' => [
                'repository' => 'App\Core\Repository\PlaceCategoryField\PlaceCategoryFieldRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'place_category_field_option' => [
                'repository' => 'App\Core\Repository\PlaceCategoryFieldOption\PlaceCategoryFieldOptionRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => false,
                'parent_column_name' => null
            ],

            'promotion_type' => [
                'repository' => 'App\Core\Repository\PromotionType\PromotionTypeRepository',
                'source_column' => 'name',
                'key_column' => 'language_key',
                'parent_structure' => true,
                'parent_column_name' => 'parent_id'
            ]
*/

        ];

    }


    public function createApplicationLanguageData()
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $languageCriteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_application', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_published', 'condition' => '=', 'value' => 1]
                ],
                "orderBy" => [
                    ["field" => "name", "value" => "ASC"]
                ]
            ];
            $languages = $this->languageRepository->findByCriteria($languageCriteria, ['id', 'code', 'name', 'status']);
            if (!$languages) {
                throw new ApiErrorException('Language data not found');
            }

            $languagesBase = $this->languageBaseRepository->findByCriteria([], ['id', 'code', 'key', 'text']);
            $languagesBase = $languagesBase ? $languagesBase : [];

            $languagesBaseArray = [];
            foreach ($languagesBase as $base) {
                $languagesBaseArray[$base['key']] = $base['text'];
            }

            $languagesTranslate = $this->languageTranslateRepository->findByCriteria([], ['id', 'code', 'key', 'text']);
            $languagesTranslate = $languagesTranslate ? $languagesTranslate : [];

            $languagesTranslateArray = [];
            foreach ($languagesTranslate as $translate) {
                $languagesTranslateArray[$translate['code']][$translate['key']] = $translate['text'];

            }

            $languageExportData = [];

            foreach ($languages as $language) {
                $languageContent = null;
                if ($language['code'] == 'en') {
                    $languageContent = $languagesBaseArray;
                } elseif (isset($languagesTranslateArray[$language['code']])) {
                    $languageContent = $languagesTranslateArray[$language['code']];
                }

                $languageExportData[$language['code']] = $languageContent;
            }

            $response = [
                'status' => 1,
                'data' => $languageExportData
            ];

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

    public function createApplicationLanguageFiles()
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $languageCriteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_application', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_published', 'condition' => '=', 'value' => 1]
                ],
                "orderBy" => [
                    ["field" => "name", "value" => "ASC"]
                ]
            ];
            $languages = $this->languageRepository->findByCriteria($languageCriteria, ['id', 'code', 'name', 'status']);
            if (!$languages) {
                throw new ApiErrorException('Language data not found');
            }

            $languagesBase = $this->languageBaseRepository->findByCriteria([], ['id', 'code', 'key', 'text']);
            $languagesBase = $languagesBase ? $languagesBase : [];

            $languagesBaseArray = [];
            foreach ($languagesBase as $base) {
                $languagesBaseArray[$base['key']] = trim($base['text']);
            }

            $languagesTranslate = $this->languageTranslateRepository->findByCriteria([], ['id', 'code', 'key', 'text']);
            $languagesTranslate = $languagesTranslate ? $languagesTranslate : [];

            $languagesTranslateArray = [];
            foreach ($languagesTranslate as $translate) {
                $clearSpaceData = trim($translate['text']);
                if($clearSpaceData){
                    $languagesTranslateArray[$translate['code']][$translate['key']] = $clearSpaceData;
                }
            }

            $applicationLanguageFolder = Config::get('app.appLanguageJsonStoredFolder');
            $myWebLanguageFolder = Config::get('app.myWebLanguageJsonStoredFolder');
            //$wwwLanguageFolder = Config::get('app.wwwLanguageJsonStoredFolder');
            $bookingEngineLanguageFolder = Config::get('app.bookingEngineLanguageJsonStoredFolder');
            $apiLanguageFolder = resource_path() . '/lang/' ;

            foreach ($languages as $language) {
                $languageContent = null;
                if ($language['code'] == 'en') {
                    $languageContent = $languagesBaseArray;
                } elseif (isset($languagesTranslateArray[$language['code']])) {
                    $languageContent = $languagesTranslateArray[$language['code']];
                }
                $filePath = $applicationLanguageFolder . '/language/' . $language['code'];
                if ($languageContent) {
                    // App Language Create
                    if (!File::exists($filePath)) {
                        File::makeDirectory($filePath, 0777, true);
                    }
                    File::put($filePath . '/common.json', json_encode($languageContent, JSON_UNESCAPED_UNICODE));

                    // Api Language Create
                    if (!File::exists($apiLanguageFolder)) {
                        File::makeDirectory($apiLanguageFolder, 0777, true);
                    }
                    File::put($apiLanguageFolder . $language['code'] . '.json', json_encode($languageContent, JSON_UNESCAPED_UNICODE));

                    // MyWeb Language Create
                    if (!File::exists($myWebLanguageFolder)) {
                        File::makeDirectory($myWebLanguageFolder, 0777, true);
                    }
                    File::put($myWebLanguageFolder . $language['code'] . '.json', json_encode($languageContent, JSON_UNESCAPED_UNICODE));

                    // www Language Create
                    /*if (!File::exists($wwwLanguageFolder)) {
                        File::makeDirectory($wwwLanguageFolder, 0777, true);
                    }
                    File::put($wwwLanguageFolder . $language['code'] . '.json', json_encode($languageContent, JSON_UNESCAPED_UNICODE));*/

                    // bookingEngine Language Create
                    if (!File::exists($bookingEngineLanguageFolder)) {
                        File::makeDirectory($bookingEngineLanguageFolder, 0777, true);
                    }
                    File::put($bookingEngineLanguageFolder . $language['code'] . '.json', json_encode($languageContent, JSON_UNESCAPED_UNICODE));

                }
            }

            try {
                Artisan::call('queue:restart');
            } catch (Exception $error) {
                Log::error($error->getMessage());
            }

            $response['status'] = 1;

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

    public function createApplicationLanguageBaseData()
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $languagesBase = $this->languageBaseRepository->findByCriteria([], ['id', 'code', 'key', 'text']);
            $languagesBase = $languagesBase ? $languagesBase : [];

            $languagesBaseArray = [];
            foreach ($languagesBase as $base) {
                $languagesBaseArray[$base['key']] = $base['text'];
            }

            $insertBaseData = [];
            foreach ($this->tableVariables as $key => $value) {
                $repository = App::make($value['repository']);
                $tableVariables = $repository->findByCriteria([]);
                $tableVariables = $tableVariables ? $tableVariables : [];
                foreach ($tableVariables as $tableVariable) {
                    if (!isset($languagesBaseArray[$tableVariable[$value['key_column']]])) {

                        $insertBaseData[] = [
                            'key' => $tableVariable[$value['key_column']],
                            'code' => 'en',
                            'text' => $tableVariable[$value['source_column']],
                            'status' => 1,
                            'created_by' => 1,
                            'updated_by' => 1,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];
                    }
                }
            }
            $insertBaseDataStatus = $this->languageBaseRepository->createAll($insertBaseData);
            if ($insertBaseDataStatus['status'] != 'success') {
                throw new Exception('api-unknown_error');

            }

            $response['status'] = 1;

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

    public function fillApplicationLanguageKeys()
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            foreach ($this->tableVariables as $key => $value) {
                print("for table => $key \n");
                $repository = App::make($value['repository']);
                $oldVariables = $repository->findByCriteria([]);
                $oldVariables = $oldVariables ? $oldVariables : [];
                $oldVariablesCollect = collect($oldVariables);
                $oldVariables = $oldVariablesCollect->keyBy('id');
                if ($value['parent_structure'] == true) {

                    $mainFacts = $oldVariablesCollect->where('parent_id', '=', null);

                    foreach ($mainFacts as $mainFact) {

                        // main fact keys,
                        $mainFactSlug = language_key($mainFact[$value['source_column']]);
                        $mainFactLanguageKey = $key . '-' . $mainFactSlug;
                        $mainFactLanguageKey = $this->keyGenerator($mainFactLanguageKey, $value['key_column'], $oldVariables, 0);

                        if ($mainFact[$value['key_column']] == null) {
                            $mainFact[$value['key_column']] = $mainFactLanguageKey;
                            $oldVariables[$mainFact['id']] = $mainFact;
                            $repository->update($mainFact['id'], [$value['key_column'] => $mainFactLanguageKey]);
                        }


                        $subFacts = $oldVariablesCollect->where('parent_id', '=', $mainFact['id']);
                        foreach ($subFacts as $subFact) {

                            // sub fact keys
                            $subFactSlug = language_key($subFact[$value['source_column']]);
                            $subFactLanguageKey = $mainFactLanguageKey . '-' . $subFactSlug;
                            $subFactLanguageKey = $this->keyGenerator($subFactLanguageKey, $value['key_column'], $oldVariables, 0);

                            if ($subFact[$value['key_column']] == null) {
                                $subFact[$value['key_column']] = $subFactLanguageKey;
                                $oldVariables[$subFact['id']] = $subFact;
                                $repository->update($subFact['id'], [$value['key_column'] => $subFactLanguageKey]);
                            }

                            $facts = $oldVariablesCollect->where('parent_id', '=', $subFact['id']);
                            foreach ($facts as $fact) {

                                if ($fact[$value['key_column']] == null) {
                                    // sub fact keys
                                    $factSlug = language_key($fact[$value['source_column']]);
                                    $factLanguageKey = $subFactLanguageKey . '-' . $factSlug;
                                    $factLanguageKey = $this->keyGenerator($factLanguageKey, $value['key_column'], $oldVariables, 0);

                                    $fact[$value['key_column']] = $factLanguageKey;
                                    $oldVariables[$fact['id']] = $fact;
                                    $repository->update($fact['id'], [$value['key_column'] => $factLanguageKey]);
                                }

                            }

                        }

                    }
                } else {
                    foreach ($oldVariables as $oldVariable) {
                        if ($oldVariable[$value['key_column']] == null) {
                            $slug = language_key($oldVariable[$value['source_column']]);
                            $languageKey = $key . '-' . $slug;
                            $languageKey = $this->keyGenerator($languageKey, $value['key_column'], $oldVariables, 0);
                            $oldVariable[$value['key_column']] = $languageKey;
                            $oldVariables[$oldVariable['id']] = $oldVariable;
                            $repository->update($oldVariable['id'], [$value['key_column'] => $languageKey]);
                        }
                    }
                }
            }

            $response['status'] = 1;

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

    protected function keyGenerator($key, $keyColumn, $oldData, $index)
    {

        $checkKey = collect($oldData)->where($keyColumn, '=', $key)->first();


        if ($checkKey != null) {

            $keyArray1 = explode('-', $key);
            $lastArray1Item = end($keyArray1);

            $keyArray2 = explode('_', $lastArray1Item);
            $lastArray2Item = end($keyArray2);
            $index++;


            if (is_numeric($lastArray2Item)) {

                array_pop($keyArray2);
                array_push($keyArray2, $index);
                $array2ToStr = implode($keyArray2, "_");


                array_pop($keyArray1);
                array_push($keyArray1, $array2ToStr);
                $array1ToStr = implode($keyArray1, "-");


                $newKey = $array1ToStr;
            } else {

                $newKey = $key . '_' . $index;
            }

            $key = $this->keyGenerator($newKey, $keyColumn, $oldData, $index);
        }
        return $key;

    }
}
