<?php

namespace App\Http\Controllers\Admin\Updater;

use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use ZipArchive;

class UpdaterController extends Controller
{
    /** updater index */
    public function index()
    {
        // check host file
        if (!file_exists(base_path('../storage/host'))) {
            return redirect()->route('admin.dashboard');
        }

        // init variables
        $currentVersion = (float)file_get_contents(storage_path('version'));
        try {
            $latestVersion = Http::timeout(8)->get('https://data.vimascript.ir/manage/version.json');
            $latestVersion = json_decode($latestVersion->body());
            $latestVersion = (float)$latestVersion->version;
        } catch (Exception $e) {
            $latestVersion = 0.0;
        }
        $hasUpdate = $latestVersion > $currentVersion;
        try {
            $changes = Http::timeout(4)->get('https://data.vimascript.ir/manage/changes.json');
            $changes = json_decode($changes->body());
        } catch (Exception $e) {
            $changes = [];
        }

        // validate changes
        foreach ($changes as $key => $change) {
            if (str_contains(request()->getHost(), 'vimascript.ir')) {
                foreach ($change->changes as $i => $text) {
                    if (str_contains($text, '▪️')) {
                        unset($change->changes[$i]);
                    }
                }
            }
        }

        // check for existing update file
        $isUpdateFileExists = false;
        if (Storage::disk('update')->exists('vimashop.zip')) {
            $isUpdateFileExists = true;
        }

        return Inertia::render('Admin/Updater/Update', [
            'details' => [
                'currentVersion' => $currentVersion,
                'latestVersion' => $latestVersion,
                'hasUpdate' => $hasUpdate,
                'isUpdateFileExists' => $isUpdateFileExists,
            ],
            'changes' => $changes
        ]);
    }

    /**
     * upload update file
     */
    public function upload(Request $request)
    {
        // send domain data to vima server
        try {
            $domainName = preg_replace('/^www\./', '', request()->getHost());
            $currentVersion = (float)file_get_contents(storage_path('version'));
            $response = Http::timeout(4)->get('https://data.vimascript.ir/api/domains/add?domain=' . $domainName . '&version=' . $currentVersion);
            if ($response->successful()) {
                $responseBody = json_decode($response->body());
                if ($responseBody->access == 'ban') {
                    return redirect()->route('admin.settings.license')->withErrors([__('messages.sentence.msg_id_896621')]);
                }
            }
        } catch (\Exception $e) {
        }

        // check host file
        if (!file_exists(storage_path('host'))) {
            return redirect()->route('admin.dashboard');
        }

        $request->validate([
            'file' => 'required|file|mimes:zip|max:204800', // max 200mb
        ]);

        $file = $request->file('file');
        $fileName = $file->getClientOriginalName();
        $fileSaveAddress = $fileName;

        if ($fileName != 'vimashop.zip') {
            return redirect()->back()->withErrors([__('messages.file_name_incorrect')]);
        }

        $uploadResult = Storage::putFileAs('update', $file, $fileSaveAddress);
        if ($uploadResult) {
            return redirect()->back()->with('message', [__('messages.file_uploaded')]);
        }

        return redirect()->back()->withErrors([__('messages.unknown_error')]);
    }

    /**
     * start update script
     */
    public function update()
    {
        ignore_user_abort(true);
        set_time_limit(0);

        // check for lockfile
        $lockFilePath = realpath($_SERVER['DOCUMENT_ROOT']) . '/update.lock';
        if (file_exists($lockFilePath)) {
            die('فروشگاه در حال بروزرسانی میباشد. لطفا لحظاتی منتظر مانده و مجدد صفحه را بارگذاری کنید.');
        }

        // check host file
        if (!file_exists(base_path('../storage/host'))) {
            return redirect()->route('admin.dashboard');
        }

        // version information
        $currentVersion = (float)file_get_contents(storage_path('version'));
        try {
            $latestVersion = Http::timeout(8)->get('https://data.vimascript.ir/manage/version.json');
            $latestVersion = json_decode($latestVersion->body());
            $latestVersion = (float)$latestVersion->version;
        } catch (Exception $e) {
            $latestVersion = 0.0;
        }
        $hasUpdate = $latestVersion > $currentVersion;

        if ($hasUpdate) {
            // update file path
            $updateFileName = 'vimashop.zip';
            $updateFilePath = Storage::disk('update')->path('vimashop.zip');
            $extractPath = Storage::disk('update')->path('/');

            // check for existing update file
            if (!Storage::disk('update')->exists('vimashop.zip')) {
                return redirect()->route('admin.updater.index');
            }

            // lock for update
            file_put_contents($lockFilePath, "locked");

            try {
                // delete cache
                File::deleteDirectory(storage_path('framework/cache/data'));
                Cache::flush();

                // delete views
                $views = File::files(storage_path('framework/views'));
                foreach ($views as $view) {
                    File::delete($view);
                }
            } catch (\Exception $e) {
            }

            // create move.php file
            $moveFileContent = <<<'PHP'
            <?php
            ignore_user_abort(true);
            set_time_limit(0);
            function deleteDirectory($dir) {
                if (!is_dir($dir)) {
                    return false;
                }

                $items = array_diff(scandir($dir), array('.', '..'));
                foreach ($items as $item) {
                    $path = $dir . DIRECTORY_SEPARATOR . $item;

                    if (is_dir($path)) {
                        deleteDirectory($path);
                    } else {
                        unlink($path);
                    }
                }

                return rmdir($dir);
            }

            $directoryPath = realpath($_SERVER['DOCUMENT_ROOT']) . '/../ecommerce';
            deleteDirectory($directoryPath);

            rename(realpath($_SERVER['DOCUMENT_ROOT']) . '/../storage/app/update/ecommerce', realpath($_SERVER['DOCUMENT_ROOT']) . '/../ecommerce');
            PHP;
            if (file_put_contents(realpath($_SERVER['DOCUMENT_ROOT']) . '/move.php', $moveFileContent)) {
                // extract update file
                $zip = new ZipArchive;
                if ($zip->open($updateFilePath) === TRUE) {
                    $zip->extractTo($extractPath);
                    $zip->close();

                    // get uploaded update version
                    $uploadedUpdateVersionPath = 'storage/version';
                    $uploadedUpdateVersion = null;
                    if (Storage::disk('update')->exists($uploadedUpdateVersionPath)) {
                        $uploadedUpdateVersion = (float)Storage::disk('update')->get($uploadedUpdateVersionPath);
                    } else {
                        File::deleteDirectory(base_path('../storage/app/update'));

                        // unlock site
                        if (file_exists($lockFilePath)) {
                            unlink($lockFilePath);
                        }

                        return redirect()->back()->withErrors([__('messages.update_file_is_incorrect')]);
                    }

                    // check versions
                    if ($currentVersion >= $uploadedUpdateVersion) {
                        File::deleteDirectory(base_path('../storage/app/update'));

                        // unlock site
                        if (file_exists($lockFilePath)) {
                            unlink($lockFilePath);
                        }

                        return redirect()->back()->withErrors([__('messages.update_file_version_is_old')]);
                    }

                    // update script version
                    if (File::exists(storage_path('app/update/storage/version'))) {
                        File::copy(storage_path('app/update/storage/version'), base_path('../storage/version'));
                    }

                    // move ecommerce
                    try {
                        include realpath($_SERVER['DOCUMENT_ROOT']) . '/move.php';
                    } catch (\Exception $e) {
                    }

                    // delete update driver files
                    Storage::disk('update')->deleteDirectory('ecommerce');
                    Storage::disk('update')->deleteDirectory('public_html');
                    Storage::disk('update')->deleteDirectory('storage');
                    unlink(realpath($_SERVER['DOCUMENT_ROOT']) . '/move.php');
                    Storage::disk('update')->delete($updateFileName);

                    try {
                        // delete cache
                        File::deleteDirectory(storage_path('framework/cache/data'));
                        Cache::flush();

                        // delete views
                        $views = File::files(storage_path('framework/views'));
                        foreach ($views as $view) {
                            File::delete($view);
                        }
                    } catch (\Exception $e) {
                    }

                    // unlock site
                    if (file_exists($lockFilePath)) {
                        unlink($lockFilePath);
                    }
                } else {
                    // unlock site
                    if (file_exists($lockFilePath)) {
                        unlink($lockFilePath);
                    }

                    return redirect()->back()->withErrors([__('messages.extract_zip_error')]);
                }

                // unlock site
                if (file_exists($lockFilePath)) {
                    unlink($lockFilePath);
                }

                return redirect()->back()->with('message', [__('messages.script_successfully_updated')]);
            } else {
                // unlock site
                if (file_exists($lockFilePath)) {
                    unlink($lockFilePath);
                }

                return redirect()->back()->withErrors([__('messages.unknown_error')]);
            }
        } else {
            // unlock site
            if (file_exists($lockFilePath)) {
                unlink($lockFilePath);
            }

            return redirect()->route('admin.updater.index');
        }
    }

    /**
     * remove update file
     */
    public function delete()
    {
        // check host file
        if (!file_exists(base_path('../storage/host'))) {
            return redirect()->route('admin.dashboard');
        }

        // update file path
        $updateFilePath = 'vimashop.zip';

        if (Storage::disk('update')->exists($updateFilePath)) {
            Storage::disk('update')->delete($updateFilePath);
        }

        return redirect()->back()->with('message', [__('messages.update_file_deleted')]);
    }
}
