<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyBrand\PropertyBrandRepository;
use App\Core\Repository\PropertyPhoto\PropertyPhotoRepository;
use App\Core\Repository\PropertyWebPhotoMapping\PropertyWebPhotoMappingRepository;
use App\Core\Validator\Property\PropertyBrandAddValidator;
use App\Core\Validator\Property\PropertyBrandPhotoValidator;
use App\Core\Service\LanguageService;

use App;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
use Intervention\Image\Facades\Image;


class PropertyBrandService
{

    private $propertyBrandRepository;
    private $propertyBrandAddValidator;
    private $propertyBrandPhotoValidator;
    private $languageService;


    public function __construct(
        PropertyBrandRepository $propertyBrandRepository,
        PropertyPhotoRepository $propertyPhotoRepository,
        PropertyWebPhotoMappingRepository $propertyWebPhotoMappingRepository,
        PropertyBrandAddValidator $propertyBrandAddValidator,
        LanguageService $languageService,
        PropertyBrandPhotoValidator $propertyBrandPhotoValidator
    )
    {
        $this->propertyBrandRepository = $propertyBrandRepository;
        $this->propertyPhotoRepository = $propertyPhotoRepository;
        $this->propertyWebPhotoMappingRepository = $propertyWebPhotoMappingRepository;
        $this->propertyBrandAddValidator = $propertyBrandAddValidator;
        $this->propertyBrandPhotoValidator = $propertyBrandPhotoValidator;
        $this->languageService = $languageService;
    }


    public function select($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->propertyBrandRepository->findByCriteria($param, $column);
            $response = [
                'status' => true,
                'data' => $data,
            ];

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

        return output($response);
    }

    public function update($id, $param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $updateResult = $this->propertyBrandRepository->update($id, $param);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $updateData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $updateData,
            ];

        } catch (ApiErrorException $e) {
            $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 updatePropertyBrand($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyBrandAddValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $photoArray = [];
            if ($params['photo']) {
                $photoArray = $this->uploadBrandPhoto($params);
                if ($photoArray['status'] != 'success') {
                    throw new ApiErrorException($photoArray['message']);
                }
                $photoArray = $photoArray['data'];
            }

            $brandCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']]
                ],
                'firstRow' => 1

            ];

            $oldBrandData = $this->propertyBrandRepository->findByCriteria($brandCriteria);

            $checkPropertyBrand = [
                ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],

            ];

            $brandColor = json_decode($params['color_codes'], true);
            $colorCodes = trim($brandColor[0]['color_code']) === '' && trim($brandColor[1]['color_code']) === '' ? null : json_encode($brandColor, true);


            $titles = [];
            $titleArray = json_decode(fillOnUndefined($params, "title", []), 1);

            if (!empty($oldBrandData['title'])) {
                $brandLanguages = (array)json_decode($oldBrandData['title'], 1);

                $arrDiffs = array_diff_key($brandLanguages, $titles);

                foreach ($arrDiffs as $key => $arrDiff) {
                    $titles[$key] = $arrDiff;
                }
            }

            foreach ($titleArray as $key => $arr) {
                $titles[$arr['language_code']] = $arr['description'];
            }


            $insertData =
                [
                    "property_id" => fillOnUndefined($params, "property_id"),
                    "title" => json_encode($titles),
                    "color_codes" => $colorCodes,
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];

            if ($photoArray) {
                $insertData['logo_path'] = $photoArray['path'];
                $insertData['logo_name'] = $photoArray['photo'];
                $insertData['logo_file_ext'] = $photoArray['extension'];
            }

            $propertyBrandResponse = $this->propertyBrandRepository->updateOrCreate($checkPropertyBrand, $insertData);


            if ($propertyBrandResponse['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            if ($oldBrandData && $params['photo'] && $photoArray) {
                $urlPath = '/property-photos/' . $oldBrandData['property_id'] . "/logo/";
                $filePath = Config::get('app.fileSystemDriver') . $urlPath;
                $oldImage250px = $filePath . $oldBrandData['logo_name'] . '_250x250' . '.' . $oldBrandData['logo_file_ext'];
                $oldImage750px = $filePath . $oldBrandData['logo_name'] . '_750x750' . '.' . $oldBrandData['logo_file_ext'];
                if (File::exists($oldImage750px)) {
                    File::delete($oldImage750px);
                }
                if (File::exists($oldImage250px)) {
                    File::delete($oldImage250px);
                }
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyBrandResponse['data']];

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

        return output($response);
    }

    public function uploadBrandPhoto($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $fileParam = [];
            $validateParams = [
                'photo' => $params['photo']
            ];

            $validationResult = $this->propertyBrandPhotoValidator->validate($validateParams);
            if ($validationResult->errors()->first()) {
                throw new ApiErrorException($validationResult->errors()->all());
            }


            $filePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . "/logo/";

            if (!File::exists($filePath)) {
                File::makeDirectory($filePath, 0777, true);
            }


            $uploadedFile = $params['photo'];
            $imageResize = Image::make($uploadedFile);
            $imageWidth = $imageResize->width();
            $imageHeight = $imageResize->height();
            if ($imageWidth < 200 && $imageHeight < 150) {
                throw new ApiErrorException('image size error');
            }

            $fileExt = $uploadedFile->getClientOriginalExtension();
            $urlPath = '/property-photos/' . $params['property_id'] . "/logo/";
            $filePath = Config::get('app.fileSystemDriver') . $urlPath;
            $fileName = time();

            if ($imageWidth >= 750 || $imageHeight >= 750) {
                if ($imageWidth >= $imageHeight) {
                    $imageResize->resize(750, null, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_750x750' . '.' . $fileExt);

                    $imageResize->resize(250, null, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_250x250' . '.' . $fileExt);
                } else {
                    $imageResize->resize(null, 750, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_750x750' . '.' . $fileExt);
                    $imageResize->resize(null, 250, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_250x250' . '.' . $fileExt);

                }
            } else {
                if ($imageWidth >= $imageHeight) {
                    $imageResize->save($filePath . $fileName . '_750x750' . '.' . $fileExt);
                    $imageResize->resize(250, null, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_250x250' . '.' . $fileExt);
                } else {
                    $imageResize->save($filePath . $fileName . '_750x750' . '.' . $fileExt);
                    $imageResize->resize(null, 250, function ($constraint) {
                        $constraint->aspectRatio();
                    })->save($filePath . $fileName . '_250x250' . '.' . $fileExt);
                }
            }
            $imageResize->destroy();
            $fileParam =
                [
                    'photo' => $fileName,
                    'path' => $urlPath,
                    'extension' => $fileExt,
                ];

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $fileParam];

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

        return output($response);
    }

    public function getPropertyBrand($params = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $requestBrand = [

                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],

                ],
                'firstRow' => 1
            ];

            $getPropertyBrand = $this->select($requestBrand);
            if ($getPropertyBrand['status'] != "success") {
                throw new ApiErrorException($getPropertyBrand['message']);
            }

            $getApplicationLanguages = $this->languageService->getApplicationLanguages();
            if ($getApplicationLanguages['status'] != 'success') {
                throw new ApiErrorException($getApplicationLanguages['message']);
            }
            $applicationLanguages = $getApplicationLanguages['data'];
            $responseLangTitle = [];

            $brandLanguages = [];
            if (!empty($getPropertyBrand['data']['title'])) {
                $brandLanguages = (array)json_decode($getPropertyBrand['data']['title'], 1);
            }

            if (!empty($getPropertyBrand['data'])) {
                $brandColors = $getPropertyBrand['data']['color_codes'];
                $getPropertyBrand = $getPropertyBrand['data'];
                $getPropertyBrand['color_codes'] = json_decode($brandColors, true);
                $getPropertyBrand['name'] = $getPropertyBrand['logo_name'];
                $getPropertyBrand['logo_name'] = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . "/logo/" . $getPropertyBrand['logo_name'] . '_250x250.' . $getPropertyBrand['logo_file_ext'];
                $brandTitle = fillOnUndefinedAndEmpty($getPropertyBrand, 'title', "[]");

                $titleLangContents = json_decode($brandTitle, 1);
                foreach ($applicationLanguages as $applicationLanguage) {
                    $langKey = $applicationLanguage['code'];
                    $responseLangTitle[] = [
                        'language_code' => $langKey,
                        'description' => isset($titleLangContents[$langKey]) ? $titleLangContents[$langKey] : null
                    ];
                }
                $appLanguages = [];
                foreach ($applicationLanguages as $applicationLanguage) {
                    $appLanguages[] = $applicationLanguage['code'];
                }

                foreach ($appLanguages as $key => $appLanguage) {
                    if (in_array($appLanguage, array_keys($brandLanguages))) {

                        $getPropertyBrand['title'] = $responseLangTitle;
                    }
                }

                $getPropertyBrand['title'] = $responseLangTitle;

            } else {
                foreach ($applicationLanguages as $applicationLanguage) {
                    $langKey = $applicationLanguage['code'];
                    $responseLangTitle[] = [
                        'language_code' => $langKey,
                        'description' => null
                    ];
                }
                $getPropertyBrand = null;
                $getPropertyBrand['title'] = $responseLangTitle;
                $getPropertyBrand['color_codes'] = json_decode('[{"color_number":1,"color_code":"#000"},{"color_number":2,"color_code":"#000"}]');
            }


            //Cover Photo
            $coverPhoto = null;
            $propertyWebPhotoMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'is_cover', 'condition' => '=', 'value' => 1],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['propertyPhoto'],
                'orderBy' => [["field" => "updated_at", "value" => "ASC"]],
                'firstRow' => true
            ];
            $propertyWebMappingPhotos = $this->propertyWebPhotoMappingRepository->findByCriteria($propertyWebPhotoMappingRequest);
            $propertyWebMappingPhotos = $propertyWebMappingPhotos ? $propertyWebMappingPhotos : [];

            if (!empty($propertyWebMappingPhotos)) {
                $coverPhoto = $propertyWebMappingPhotos['property_photo']['photoUrl']['default'];
            } else {

                $propertyDefaultPhotoRequest = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                        ['field' => 'is_default', 'condition' => '=', 'value' => 1],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ],
                    'firstRow' => true
                ];
                $propertyDefaultPhoto = $this->propertyPhotoRepository->findByCriteria($propertyDefaultPhotoRequest);
                $propertyDefaultPhoto = $propertyDefaultPhoto ? $propertyDefaultPhoto : [];


                if (!empty($propertyDefaultPhoto)) {
                    $coverPhoto = $propertyDefaultPhoto['photoUrl']['default'];
                }
            }

            $getPropertyBrand['cover_photo'] = empty($coverPhoto) ? 'https://api.extranetwork.com/assets/img/main-image.png' : $coverPhoto;
            //Cover Photo

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

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

        return output($response);
    }

    public function clearBrandLogo($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $requestBrand = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],

                ],
                'firstRow' => 1
            ];

            $getPropertyBrand = $this->select($requestBrand);

            if ($getPropertyBrand['status'] != "success") {
                throw new ApiErrorException($getPropertyBrand['message']);
            }

            if (empty($getPropertyBrand['data'])) {
                throw new ApiErrorException("Property Not Found");
            }

            $brandId = $getPropertyBrand['data']['id'];

            $brandUpdateData = [
                "logo_path" => null,
                "logo_name" => null,
                "logo_file_ext" => null,
                "updated_by" => fillOnUndefined($params, 'user_id'),
                "updated_at" => time(),
            ];

            $updatedBrand = $this->update($brandId, $brandUpdateData);

            if (!empty($updatedBrand['data'])) {
                $brandLogoPath = Config::get('app.fileSystemDriver') . $getPropertyBrand['data']['logo_path'];
                $brandLogoName = $getPropertyBrand['data']['logo_name'];
                $brandLogoExtension = $getPropertyBrand['data']['logo_file_ext'];

                $filename1 = $brandLogoPath . $brandLogoName . '_250x250' . '.' . $brandLogoExtension;
                $filename2 = $brandLogoPath . $brandLogoName . '_750x750' . '.' . $brandLogoExtension;

                if (File::exists($filename1) && File::exists($filename2)) {
                    File::delete([$filename1, $filename2]);
                }
            }

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

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

        return output($response);

    }


}
