<?php

namespace App\Http\Controllers\WEB\Admin;

use App\Http\Controllers\Controller;
use App\Models\CustomPagination;
use App\Models\Language;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Stichoza\GoogleTranslate\GoogleTranslate;

class LanguageController extends Controller {

    public function adminLnagugae( $code ) {
        $language = Language::where( "code", $code )->firstOrFail();
        $arrayData = include resource_path( 'lang/' . $code . '/admin.php' );

        $data = $this->collectionPagination( $arrayData );

        return view( 'admin.admin_language', compact( 'data' ) );
    }

    public function updateAdminLanguage( Request $request, $code ) {
        $this->updateLanguageFile( $request, $code, 'admin.php' );

        $notification = trans( 'admin_validation.Update Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );
        return redirect()->back()->with( $notification );
    }

    public function adminValidationLnagugae( $code ) {
        $language = Language::where( "code", $code )->firstOrFail();
        $arrayData = include resource_path( 'lang/' . $code . '/admin_validation.php' );

        $data = $this->collectionPagination( $arrayData );

        return view( 'admin.admin_validation_language', compact( 'data' ) );
    }

    public function updateAdminValidationLnagugae( Request $request, $code ) {
        $this->updateLanguageFile( $request, $code, 'admin_validation.php' );

        $notification = trans( 'admin_validation.Update Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );
        return redirect()->back()->with( $notification );
    }

    public function websiteLanguage( $code ) {
        $language = Language::where( "code", $code )->firstOrFail();
        $arrayData = include resource_path( 'lang/' . $code . '/user.php' );

        $data = $this->collectionPagination( $arrayData );
        return view( 'admin.language', compact( 'data' ) );
    }

    public function updateLanguage( Request $request, $code ) {
        $this->updateLanguageFile( $request, $code, 'user.php' );

        $notification = trans( 'admin_validation.Update Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );
        return redirect()->back()->with( $notification );
    }

    public function websiteValidationLanguage( $code ) {
        $language = Language::where( "code", $code )->firstOrFail();
        $arrayData = include resource_path( 'lang/' . $code . '/user_validation.php' );

        $data = $this->collectionPagination( $arrayData );

        return view( 'admin.website_validation_language', compact( 'data' ) );
    }

    public function updateValidationLanguage( Request $request, $code ) {
        $this->updateLanguageFile( $request, $code, 'user_validation.php' );

        $notification = trans( 'admin_validation.Update Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );
        return redirect()->back()->with( $notification );
    }

    /**
     * Retrieves the index view for the admin languages page.
     *
     * @return \Illuminate\Contracts\View\View
     */
    public function index() {
        $default_lang_info = Language::where( 'status', 1 )->first();
        return view( 'admin.languages', [
            'languages' => Language::all(),
            'is_default' => $default_lang_info,
        ] );
    }

    /**
     * Create a new view for the admin to create a language.
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function create() {
        return view( 'admin.create_language' );
    }

    /**
     * Stores the language data from the request.
     *
     * @param Request $request The request object.
     * @return \Illuminate\Http\RedirectResponse Redirect to the language index page.
     */
    public function store( Request $request ) {
        $rules = [
            'name'      => 'required|unique:languages',
            'code'      => 'required|unique:languages',
            'direction' => 'required',
        ];

        $customMessages = [
            'name.required'      => trans( 'admin_validation.Name is required' ),
            'code.required'      => trans( 'admin_validation.Code is required' ),
            'direction.required' => trans( 'admin_validation.Direction is required' ),
        ];

        $this->validate( $request, $rules, $customMessages );

        $lang = Language::create( $request->only( 'name', 'code', 'direction' ) );

        if ( $lang ) {
            $code = strtolower( $lang->code );
            $parentDir = dirname( app_path() );

            $files = [
                'admin_validation.php',
                'admin.php',
                'user.php',
                'user_validation.php',
            ];

            foreach ( $files as $file ) {
                $sourcePath = $parentDir . "/resources/lang/en/{$file}";
                $destinationPath = $parentDir . "/resources/lang/{$code}/{$file}";

                if ( file_exists( $sourcePath ) ) {
                    if ( !file_exists( dirname( $destinationPath ) ) ) {
                        mkdir( dirname( $destinationPath ) );
                    }

                    copy( $sourcePath, $destinationPath );
                }
            }
        }

        $notification = trans( 'admin_validation.Created Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );
        return redirect()->route( 'admin.languages.index' )->with( $notification );
    }

    /**
     * Edit a language.
     *
     * @param int $id The ID of the language to edit.
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException If the language is not found.
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View The view for editing the language.
     */
    public function edit( $id ) {
        $language = Language::findOrFail( $id );

        return view( 'admin.edit_language', [
            'language' => $language,
        ] );
    }

    /**
     * Updates a language in the database.
     *
     * @param Request $request The HTTP request object.
     * @param int $id The ID of the language to update.
     * @throws \Throwable If an error occurs while deleting the old language code folder.
     * @return \Illuminate\Http\RedirectResponse Redirects to the language index page with a success notification.
     */
    public function update( Request $request, $id ) {
        $rules = [
            'name'      => 'required|unique:languages,name,' . $id,
            'direction' => 'required',
        ];

        $customMessages = [
            'name.required'      => trans( 'admin_validation.Name is required' ),
            'code.required'      => trans( 'admin_validation.Code is required' ),
            'name.unique'        => trans( 'admin_validation.Name is taken' ),
            'code.unique'        => trans( 'admin_validation.Code is taken' ),
            'direction.required' => trans( 'admin_validation.Direction is required' ),
        ];

        $this->validate( $request, $rules, $customMessages );

        $lang = Language::findOrFail( $id );
        $oldCode = $lang->code;
        $language = $lang->update( $request->only( 'name', 'direction' ) );
        $code = strtolower( $lang->code );

        if ( $language && ( $oldCode !== $code ) && ( $code !== 'en' ) ) {
            $parentDir = dirname( app_path() );

            $files = [
                'admin_validation.php',
                'admin.php',
                'user.php',
                'user_validation.php',
            ];

            foreach ( $files as $file ) {
                $sourcePath = $parentDir . "/resources/lang/en/{$file}";
                $destinationPath = $parentDir . "/resources/lang/{$code}/{$file}";

                if ( file_exists( $sourcePath ) ) {
                    if ( !file_exists( dirname( $destinationPath ) ) ) {
                        mkdir( dirname( $destinationPath ) );
                    }

                    copy( $sourcePath, $destinationPath );
                }
            }

            if ( $oldCode !== $code && $code !== 'en' ) {
                $parentDir = dirname( app_path() );
                $destinationPath = $parentDir . "/resources/lang/{$oldCode}";
                try {
                    $this->deleteFolder( $destinationPath );
                } catch ( \Throwable $th ) {
                    //throw $th;
                }
            }
        }

        $notification = trans( 'admin_validation.Updated Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );

        return redirect()->route( 'admin.languages.index' )->with( $notification );
    }

    /**
     * Destroy a language by its ID.
     *
     * @param int $id The ID of the language to be destroyed.
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy( $id ) {
        $language = Language::findOrFail( $id );
        $code = $language->code;
        if ( $language->code == app()->getLocale() || $language->code == 'en' ) {
            $notification = trans( 'admin.Deleting Failed' );
            $notification = array( 'messege' => $notification, 'alert-type' => 'error' );

            return redirect()->route( 'admin.languages.index' )->with( $notification );
        }

        if ( $language->delete() && $code !== 'en' ) {
            $parentDir = dirname( app_path() );
            $destinationPath = $parentDir . "/resources/lang/{$code}";
            $this->deleteFolder( $destinationPath );
        }

        $notification = trans( 'admin_validation.Deleted Successfully' );
        $notification = array( 'messege' => $notification, 'alert-type' => 'success' );

        return redirect()->route( 'admin.languages.index' )->with( $notification );
    }

    public function translateAll( Request $request ) {
        $files = [
            'admin_validation',
            'admin',
            'user',
            'user_validation',
        ];

        if ( in_array( $request->file, $files ) ) {
            $texts = json_decode( html_entity_decode( $request->texts ), true );

            $filePath = resource_path( 'lang/' . $request->code . '/' . $request->file . '.php' );
            $existingData = include $filePath;

            $tr = new GoogleTranslate( $request->code );

            foreach ( $texts as $index => $value ) {
                $existingData[$index] = $tr->translate( $value ) ?? $value;
            }

            file_put_contents( $filePath, '<?php' . PHP_EOL . 'return ' . var_export( $existingData, true ) . ';' . PHP_EOL );

            return response()->json( [
                'success' => true,
                'message' => "All texts translated successfully!",
            ] );
        }
        return response()->json( [
            'success' => false,
            'message' => "File Not Found!",
        ], 404 );
    }

    /**
     * Deletes a folder and all its contents recursively.
     *
     * @param string $folderPath The path to the folder to be deleted.
     * @return void
     */
    private function deleteFolder( $folderPath ) {
        if ( is_dir( $folderPath ) ) {
            $files = scandir( $folderPath );
            foreach ( $files as $file ) {
                if ( $file != '.' && $file != '..' ) {
                    $this->deleteFolder( $folderPath . '/' . $file );
                }
            }
            rmdir( $folderPath );
        } else {
            unlink( $folderPath );
        }
    }

    //Paginate language file array data
    private function collectionPagination( $data ) {
        $perPage = CustomPagination::where( 'id', 4 )->first()->qty;
        Paginator::useBootstrap();
        $currentPage = LengthAwarePaginator::resolveCurrentPage();
        $dataCollection = collect( $data );
        $currentPageItems = $dataCollection->slice(  ( $currentPage - 1 ) * $perPage, $perPage )->all();
        $paginationData = new LengthAwarePaginator( $currentPageItems, $dataCollection->count(), $perPage, $currentPage, [
            'path' => LengthAwarePaginator::resolveCurrentPath(),
        ] );

        return $paginationData;
    }
    //update paginate file data
    private function updateLanguageFile( $request, $code, $fileName ) {
        $filePath = resource_path( 'lang/' . $code . '/' . $fileName );
        $existingData = include $filePath;

        foreach ( $request->values as $index => $value ) {
            $existingData[$index] = $value;
        }

        file_put_contents( $filePath, '<?php' . PHP_EOL . 'return ' . var_export( $existingData, true ) . ';' . PHP_EOL );
    }

    public function updateStatus( Language $language ): JsonResponse {
        try {
            DB::beginTransaction();
            if ( $language->status == 0 ) {
                Language::where( 'status', 1 )->update( ['status' => '0'] );
            }

            if (Language::where('status', 1)->whereNot('id',$language->id)->count() == 0 && $language->status == 1) {
                Language::where( 'id', 1 )->update( ['status' => 1] );
            } else {
                $language->status = $language->status ? 0 : 1;
            }

            $action = $language->save();

            // Set session and cache for the default language
            $default_lang_info = Language::where( 'status', 1 )->first();
            if ( $default_lang_info ) {
                session( ['lang' => $default_lang_info->code] );
                session( ['text_direction' => $default_lang_info->direction] );
                Cache::put( 'default_lang', $default_lang_info->code );
            }

            DB::commit();
            return response()->json( [
                'status'  => $action,
                'message' => $action ? trans( 'admin_validation.Updated Successfully' ) : trans( 'admin_validation.Update Failed' ),
            ] );

        } catch ( \Exception $e ) {
            DB::rollBack();
            return response()->json( [
                'status'  => false,
                'message' => trans( 'admin_validation.Update Failed' ) . ' ' . $e->getMessage(),
            ] );
        }
    }
}
