<?php

    namespace App\Repositories\Eloquent;

    use App\Exceptions\GeneralException;
    use App\Helpers\Helper;
    use App\Library\Tool;
    use App\Models\Plugins;
    use App\Repositories\Contracts\PluginsRepository;
    use Exception;
    use Illuminate\Http\Request;
    use ZipArchive;

    class EloquentPluginsRepository extends EloquentBaseRepository implements PluginsRepository
    {
        /**
         * EloquentPluginsRepository constructor.
         *
         * @param Plugins $plugin
         */
        public function __construct(Plugins $plugin)
        {
            parent::__construct($plugin);
        }


        /**
         * Uploads a plugin to a temporary location, extracts its contents, validates its metadata,
         * and moves it to the plugins directory. Throws exceptions if the uploaded file is invalid
         * or if metadata validation fails.
         *
         * @param Request $request The request object containing the uploaded file.
         * @return string The name of the uploaded plugin in the format 'vendor/name'.
         * @throws GeneralException If the zip archive is invalid, the plugin package is invalid,
         * @throws Exception
         *                          or metadata validation fails.
         */
        public function upload(Request $request)
        {

            $pluginsPath = storage_path('app/plugins');

            // move file to temp place
            $tmp_path  = storage_path('tmp/uploaded_plugin_' . time());
            $file_name = $request->file('file')->getClientOriginalName();
            $request->file('file')->move($tmp_path, $file_name);
            $tmp_zip = Helper::join_paths($tmp_path, $file_name);

            // read zip file check if zip archive invalid
            $zip = new ZipArchive();
            if ($zip->open($tmp_zip, ZipArchive::CREATE) !== true) {
                throw new GeneralException('Invalid zip archive');
            }

            // unzip template archive and remove zip file
            $zip->extractTo($tmp_path);
            $zip->close();
            unlink($tmp_zip);

            // read plugin file
            if ( ! is_file($configFile = $tmp_path . '/composer.json')) {
                throw new GeneralException('Invalid plugin package. No meta data found');
            }

            try {
                $config = json_decode(file_get_contents($configFile), true);
            } catch (Exception) {
                throw new GeneralException('Invalid plugin package. Cannot parse meta data');
            }

            $names = explode('/', $config['name']);
            // check valid plugin name
            if (count($names) != 2) {
                throw new GeneralException('Invalid plugin package. No meta data found');
            }
            $pluginVendor = $names[0];
            $pluginName   = $names[1];

            // check if plugin exist
            $pluginsVendorPath = $pluginsPath . '/' . $pluginVendor;
            $pluginsSourcePath = $pluginsVendorPath . '/' . $pluginName;

            // check if overwrite plugin
            if ($request->overwrite) {
                $config['overwrite'] = true;
            }

            // throw exception if any required key is missing
            self::validateMetaData($config);

            // create folders
            $paths = [
                $pluginsPath,
                $pluginsVendorPath,
                $pluginsSourcePath,
            ];

            foreach ($paths as $path) {
                if ( ! file_exists($path)) {
                    mkdir($path, 0777, true);
                }
            }

            // move from tmp to storage/app/plugins
            Tool::xdelete($pluginsSourcePath);
            if ( ! file_exists($pluginsSourcePath)) {
                mkdir($pluginsSourcePath, 0777, true);
            }
            Tool::xcopy($tmp_path, $pluginsSourcePath);
            Tool::xdelete($tmp_path);

            return $config['name'];
        }

        public function enable(Plugins $plugin)
        {

        }

        public function disable(Plugins $plugin)
        {

        }

        public function uninstall(Plugins $plugin)
        {

        }

        public function settings(Plugins $plugin)
        {

        }

        /**
         * @throws Exception
         */
        public static function validateMetaData($config = []): void
        {
            // Check required keys
            $requiredKeys = ['name', 'title', 'version', 'app_version']; // ['name', 'title', 'version', 'app_version'];
            foreach ($requiredKeys as $key) {
                if ( ! array_key_exists($key, $config)) {
                    throw new GeneralException("Invalid plugin package. Unknown '{$key}'");
                }
            }


            // Check app version
            $currentVersion  = config('app.version');
            $requiredVersion = $config['app_version'];
            $checked         = version_compare($currentVersion, $requiredVersion, '>=');
            if ( ! $checked) {
                throw new GeneralException(trans('messages.plugin.error.version', [
                    'current'  => $currentVersion,
                    'required' => $requiredVersion,
                ]));
            }

            // // Check license type
            // if (empty(Setting::get('license_type'))) {
            //     throw new \Exception("The uploaded plugin requires a valid license of ultimate sms to proceed");
            // }

            // // Check license type
            // if (Setting::get('license_type') != 'extended') {
            //     throw new \Exception("The uploaded plugin requires an 'Extended' license of ultimate sms to proceed, your current license is 'Regular'");
            // }
        }

    }
