<?php

namespace addons\webman\controller;

use addons\webman\Admin;
use addons\webman\form\MyEditor;
use addons\webman\model\AppVersion;
use addons\webman\model\Channel;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\form\Watch;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\support\Request;
use RarArchive;
use Respect\Validation\Exceptions\Exception;
use ZipArchive;


/**
 * 版本管理
 */
class AppVersionController
{
    protected $model;

    public function __construct()
    {
        $this->model = plugin()->webman->config('database.app_version_model');

    }

    /**
     * 版本
     * @auth true
     * @return Card
     */
    public function index(): Card
    {
        return Card::create(Tabs::create()
            ->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID), $this->androidList())
            ->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS), $this->iosList())
            ->type('card')
            ->destroyInactiveTabPane()
        );
    }

    /**
     * 安装版本
     * @return Grid
     */
    public function androidList(): Grid
    {
        return Grid::create(new $this->model(), function (Grid $grid) {
            $grid->model()->where('system_key', AppVersion::SYSTEM_KEY_ANDROID)->orderBy('id', 'desc');
            $this->getList($grid, AppVersion::SYSTEM_KEY_ANDROID);
        });
    }

    /**
     * 苹果版本
     * @return Grid
     */
    public function iosList(): Grid
    {
        return Grid::create(new $this->model(), function (Grid $grid) {
            $grid->model()->where('system_key', AppVersion::SYSTEM_KEY_IOS)->orderBy('id', 'desc');
            $this->getList($grid, AppVersion::SYSTEM_KEY_IOS);
        });
    }

    /**
     * 版本列表
     * @param $grid
     * @param $systemKey
     */
    public function getList($grid, $systemKey)
    {
        $grid->title(admin_trans('app_version.title'));
        $exAdminFilter = Request::input('ex_admin_filter', []);
        if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
            $grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
        }
        if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
            $grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
        }
        $grid->autoHeight();
        $grid->bordered(true);
        $grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
        $grid->column('system_key', admin_trans('app_version.fields.system_key'))->align('center');
        $grid->column('app_version', admin_trans('app_version.fields.app_version'));
        $grid->column('app_version_key', admin_trans('app_version.fields.app_version_key'))->align('center');
        $grid->column('apk_url', admin_trans('app_version.fields.apk_url'))->align('center');
        $grid->column('force_update', admin_trans('app_version.fields.force_update'))->switch([[1 => ''], [0 => '']])->align('center');
        $grid->column('hot_update', admin_trans('app_version.fields.hot_update'))->switch([[1 => ''], [0 => '']])->align('center');
        $grid->column('regular_update', admin_trans('app_version.fields.regular_update'))->align('center');
        $grid->column('notes', admin_trans('app_version.fields.notes'))->align('center');
        $grid->column('status', admin_trans('app_version.fields.status'))->switch([[1 => ''], [0 => '']])->align('center');
        $grid->column('created_at', admin_trans('app_version.fields.created_at'))->align('center');
        $grid->hideDelete();
        $grid->hideSelection();
        $grid->filter(function (Filter $filter) {
            $filter->eq()->select('department_id')
                ->showSearch()
                ->style(['width' => '200px'])
                ->dropdownMatchSelectWidth()
                ->placeholder(admin_trans('channel.fields.name'))
                ->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
            $filter->eq()->select('status')
                ->placeholder(admin_trans('app_version.fields.status'))
                ->options([
                    1 => admin_trans('post.normal'),
                    0 => admin_trans('post.disable')
                ]);
            $filter->form()->hidden('created_at_start');
            $filter->form()->hidden('created_at_end');
            $filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
        });
        $grid->setForm()->drawer($this->form($systemKey));
        $grid->quickSearch();
    }

    /**
     * 添加修改版本
     * @auth true
     */
    public function form($systemKey): Form
    {
        ini_set('memory_limit', '512M');
        Form::extend('myEditor', MyEditor::class);
        return Form::create(new $this->model, function (Form $form) use ($systemKey) {
            $form->title(admin_trans('app_version.title'));
            $form->radio('system_key', admin_trans('app_version.fields.system_key'))
                ->button()
                ->default($systemKey)
                ->options([
                    AppVersion::SYSTEM_KEY_ANDROID => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID),
                    AppVersion::SYSTEM_KEY_IOS => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS),
                ])->required();
            $form->dateTime('regular_update', admin_trans('app_version.fields.regular_update'))->required();
            $form->select('department_id', admin_trans('slider.fields.department_id'))
                ->options($this->getChannelOptions())->required();
            $form->text('app_version', admin_trans('app_version.fields.app_version'))->rule([
                'regex:/^\d+\.\d+\.\d+$/' => admin_trans('app_version.app_version_regex')
            ])->maxlength(50)->required();
            $form->text('app_version_key', admin_trans('app_version.fields.app_version_key'))->disabled(true)->maxlength(50)->required();
            $form->watch([
                'app_version' => function ($value, Watch $watch) {
                    $versionNumbers = explode('.', $value);
                    $newVersion = implode('', $versionNumbers);
                    $watch['app_version_key'] = $newVersion;
                },
            ]);
            $form->row(function (Form $form) {
                $form->switch('status', admin_trans('app_version.fields.status'))->span(8)->required();
                $form->switch('force_update', admin_trans('app_version.fields.force_update'))->span(8)->required();
                $form->switch('hot_update', admin_trans('app_version.fields.hot_update'))
                    ->default(0)
                    ->when('==', 1, function (Form $form) {
                        $form->file('apk_url', admin_trans('app_version.hot_apk_url'))
                            ->directory('app_version')
                            ->type('file')
                            ->ext(['zip'])
                            ->chunkSize(1)
                            ->chunk()
                            ->limit(1)
                            ->fileSize('200MB')->hideFinder()->required();
                    })->when('==', 0, function (Form $form) {
                        $form->text('apk_url', admin_trans('app_version.fields.apk_url'))->ruleUrl()->maxlength(200)->required();
                    })
                    ->span(8)
                    ->required();
            }, null);
            $form->textarea('notes', admin_trans('app_version.fields.notes'))->maxlength(125)->bindAttr('rows', 3);
            $form->myEditor('update_content', admin_trans('app_version.fields.update_content'));
            $form->hidden('user_id')->value(!empty(Admin::user()) ? Admin::user()->id : 0);
            $form->hidden('user_name')->value(!empty(Admin::user()) ? Admin::user()->username : '');
            $form->hidden('hot_update_url');
            $form->layout('vertical');
            $form->saving(function (Form $form) {
                $apkUrl = $form->input('apk_url');
                $hotUpdate = $form->input('hot_update');
                $hotUpdateUrl = $form->input('hot_update_url');
                $appVersionKey = $form->input('app_version_key');
                if (!$apkUrl) {
                    return message_error(admin_trans('app_version.missing_package_address'));
                }
                if (!$appVersionKey) {
                    return message_error(admin_trans('app_version.app_version_key_not_found'));
                }
                if (AppVersion::query()->where('department_id', $form->input('department_id'))->where('app_version_key', $appVersionKey)->exists()) {
                    return message_error(admin_trans('app_version.app_version_key_exists'));
                }
                if ($hotUpdate == 1) {
                    $apkUrl = str_replace(env('APP_DOMAIN'), '', $apkUrl);
                    if (!file_exists(public_path() . $apkUrl)) {
                        return message_error(admin_trans('app_version.upload_update_package'));
                    }
                    if (empty($hotUpdateUrl)) {
                        $extension = pathinfo($apkUrl, PATHINFO_EXTENSION);
                        $fileName = pathinfo($apkUrl, PATHINFO_FILENAME);
                        if (!$extension || !$fileName) {
                            return message_error(admin_trans('app_version.hot_apk_url_error'));
                        }
                        // 解压压缩包
                        $hotUrl = $this->decompression($appVersionKey, $extension, $apkUrl);
                        $form->input('hot_update_url', $hotUrl);
                    }
                }
            });
        });
    }

    /**
     * 筛选部门/渠道
     * @return array
     */
    public function getChannelOptions(): array
    {
        $channelList = Channel::query()->orderBy('created_at', 'desc')->get();
        $data = [];
        /** @var Channel $channel */
        foreach ($channelList as $channel) {
            $data[$channel->department_id] = $channel->name;
        }
        return $data;
    }

    /**
     * @param $appVersionKey
     * @param string $type
     * @param string $file
     * @return string|void
     * @throws \Exception
     */
    public function decompression($appVersionKey, string $type = '', string $file = '')
    {
        try {
            $file = public_path() . $file;
            $savePath = '/storage/app_version/' . $appVersionKey;
            $newPath = public_path() . $savePath;
            if (!file_exists($newPath)) {
                //检查是否有该文件夹，如果没有就创建，并给予最高权限
                mkdir($newPath, 0755, true);
            }
            switch ($type) {
                case 'zip':
                    $zip = new ZipArchive;
                    if ($zip->open($file) === TRUE) {
                        $zip->extractTo($newPath);
                        $zip->close();
                        return env('APP_DOMAIN') . $savePath;
                    } else {
                        throw new \Exception(admin_trans('app_version.decompression_failed'));
                    }
                case 'rar':
                    $file = RarArchive::open($file);
                    if ($file !== FALSE) {
                        $entries = $file->getEntries();
                        foreach ($entries as $entry) {
                            $entry->extract($newPath);
                        }
                        $file->close();
                        return env('APP_DOMAIN') . $savePath;
                    } else {
                        throw new \Exception(admin_trans('app_version.decompression_failed'));
                    }
            }
        } catch (Exception $e) {
            throw new \Exception($e->getMessage());
        }
    }
}
