<?php

namespace addons\repair\controller;

use app\common\controller\Addons;

class Admin extends Addons
{
    private static $param;

    public function initialize()
    {
        parent::initialize();
        self::$param = input('param.');
    }

    function index()
    {
        $max_id = db('repair_log')->max('id');
        $data = db('repair_log')->order('create_time desc')->paginate()->toArray();
        $this->init_pager($data['total']);
        if (!empty($data['data'])) {
            foreach ($data['data'] as $k => $v) {
                if ($v['id'] == $max_id) {
                    if ($v['status'] == 1) $data['data'][$k]['back'] = 1;
                    if ($v['status'] == 0) $data['data'][$k]['repair'] = 1;
                }
            }
        }
        $this->assign('data', $data['data']);
        $this->fetch();
    }

    /**
     * 日志详情
     * @param int $id
     */
    public function log()
    {
        $id = self::$param['id'] ?? 0;
        if ($id) {
            $rs = db('repair_data')->where('log_id', '=', $id)->select();
            if (!empty($rs)) {
                $columns = load_columns(0);
                foreach ($rs as $k => $v) {
                    $rs[$k]['column'] = isset($columns[$v['relation_id']]) ? $columns[$v['relation_id']] : '';
                    $rs[$k]['name'] = ($v['model'] == 'column' ? '栏目' : ($v['model'] == 'user' ? '用户' : '区块')) . '【' . $v['name'] . '】';
                }
            }
            $this->assign('rs', $rs);
        }
        $this->fetch();
    }

    /**
     * 开始检测数据
     */
    public function check()
    {
        $error = [];
        //检测用户数据
        $group = db('user_group')->select();
        $user = model('app\user\model\User')->select()->toArray();
        if (!empty($group) && !empty($user)) {
            $user_data = [];
            foreach ($user as $k => $v) {
                if (!empty($v['fields'])) $user_data[$v['group_id']][] = $v;
            }
            if (!empty($user_data)) $error = array_merge($error, $this->handle($group, $user_data, 'user'));
        }
        //检测栏目数据
        $columns = load_columns(0);
        $data = model('app\index\model\Data')->field('id,area_id,fields,column_id')->select()->toArray();
        if (!empty($columns) && !empty($data)) {
            $column_data = [];
            foreach ($data as $k => $v) {
                if (!empty($v['fields'])) $column_data[$v['column_id']][] = $v;
            }
            if (!empty($column_data)) $error = array_merge($error, $this->handle($columns, $column_data, 'column'));
        }
        //检测区块数据
        $block = db('block')->select();
        $block_data = model('app\block\model\Data')->select()->toArray();
        if (!empty($block) && !empty($block_data)) {
            $data = [];
            foreach ($block_data as $k => $v) {
                if (!empty($v['fields'])) $data[$v['block_id']][] = $v;
            }
            if (!empty($data)) $error = array_merge($error, $this->handle($block, $data, 'block'));
        }
        //加载所有扩展字段
        $rs = model('app\common\model\Fields')->order('list_order asc')->select();
        if (!empty($rs)) {
            foreach ($rs as $k => $v) {
                if (in_array($v['type'], [1, 2, 3])) {
                    //下拉，多选，单选
                    if (!empty($v['value'])) {
                        if (!is_array($v['value'])) {
                            $new = json_decode(stripcslashes($v['value']), 1);
                            $new = is_array($new) ? $new : '';
                            $error[] = [
                                'msg' => '扩展字段下拉、单选或多选，选项值为非数组格式',
                                'relation_id' => $v['relation_id'],
                                'data_id' => $v['id'],
                                'old' => json_encode($v['value']),
                                'new' => $new,
                                'name' => $v['name'],
                                'model' => ''
                            ];
                        }
                    }
                }
                if (in_array($v['type'], [0, 4])) {
                    //单文本，文本域
                    if (!empty($v['value'])) {
                        $error[] = [
                            'msg' => '扩展字段为单文本或文本域，选项值不为空',
                            'relation_id' => $v['relation_id'],
                            'data_id' => $v['id'],
                            'old' => json_encode($v['value']),
                            'new' => '',
                            'name' => $v['name'],
                            'model' => ''
                        ];
                    }
                }
            }
        }
        if (!empty($error)) {
            $log = [
                'create_time' => time(),
                'count' => count($error),
                'status' => 0,
            ];
            $log_id = db('repair_log')->insertGetId($log);
            foreach ($error as $k => $v) {
                $error[$k]['log_id'] = $log_id;
                if (empty($v['old'])) $error[$k]['old'] = NULL;
                if (empty($v['new'])) $error[$k]['new'] = NULL;
            }
            db('repair_data')->insertAll($error);
            $this->redirect(addons_url('repair/admin/log', ['id' => $log_id]));
        } else {
            $this->success('数据检测完成，未找到异常数据', addons_url('repair/admin/index'));
        }
    }

    /**
     * 修复/还原 数据
     */
    function repair()
    {
        $id = self::$param['id'] ?? 0;
        $back = self::$param['back'] ?? 0;
        $max = db('repair_log')->max('id');
        if ($id != $max) $this->error('很抱歉，只能对最新的检测结果进行' . ($back ? '还原' : '修复'));
        $log = db('repair_log')->where('id', '=', $id)->find();
        if (!empty($log)) {
            if (!$back && $log['status'] != 0) $this->error('您已修复过数据');
            if ($back && $log['status'] != 1) $this->error('您还未修复数据');
            $data = db('repair_data')->where('log_id', '=', $id)->order('id asc')->select();
            $repair_data = [];
            foreach ($data as $k => $v) {
                if (empty($v['model'])) {
                    $repair_data['fields'][] = [
                        'id' => $v['data_id'],
                        'value' => $back ? $v['old'] : $v['new']
                    ];
                } else {
                    $repair_data[$v['model']][] = [
                        'id' => $v['data_id'],
                        'fields' => json_decode(($back ? $v['old'] : $v['new']), 1)
                    ];
                }
            }
            foreach ($repair_data as $k => $v) {
                if ($k == 'column') {
                    model('app\index\model\Data')->saveAll($v);
                }
                if ($k == 'user') {
                    model('app\user\model\User')->saveAll($v);
                }
                if ($k == 'block') {
                    model('app\block\model\Data')->saveAll($v);
                }
                if ($k == 'fields') {
                    foreach ($v as $kk => $vv) db('fields')->where('id', '=', $vv['id'])->update(['value' => $vv['value']]);
                }
            }
            if ($back) {
                db('repair_log')->where('id', '=', $id)->setField('status', 0);
            } else {
                db('repair_log')->where('id', '=', $id)->setField('status', 1);
            }
            $this->success('数据' . ($back ? '还原' : '修复') . '成功');
        }
        $this->error('未找到指定的检测日志');
    }

    /**
     * 处理并返回异常数据
     * @param $class 类（栏目，用户组，区块）
     * @param $data 对应类下的数据
     */
    function handle(array $class, array $data, $model)
    {
        $error = [];
        $class_name = $model == 'column' ? '栏目' : ($model == 'user' ? '用户' : '区块');
        foreach ($class as $k => $v) {
            $fields = load_fields($v['id'], 0, '', '', $model);
            if (!empty($fields) && !empty($data[$v['id']])) {
                foreach ($data[$v['id']] as $kk => $vv) {
                    if (!empty($vv['fields'])) {
                        $old_data = $vv['fields'];
                        $diff = array_diff(array_keys($vv['fields']), array_keys($fields));
                        if (!empty($diff)) {
                            $error[] = [
                                'msg' => $class_name . '下不存在字段【' . join(',', $diff) . '】',
                                'relation_id' => $v['id'],
                                'data_id' => $vv['id'],
                                'old' => $old_data,
                                'new' => empty(array_intersect(array_keys($vv['fields']), array_keys($fields))) ? '' : get_array_keys($vv['fields'], array_intersect(array_keys($vv['fields']), array_keys($fields)), 1),
                                'model' => $model,
                                'name' => $v['name']
                            ];
                            $vv['fields'] = empty(array_intersect(array_keys($vv['fields']), array_keys($fields))) ? '' : get_array_keys($vv['fields'], array_intersect(array_keys($vv['fields']), array_keys($fields)), 1);
                        }
                        if (!empty($vv['fields'])) {
                            foreach ($vv['fields'] as $kkk => $vvv) {
                                if ($fields[$kkk]['type'] == 2 && !is_array($vvv)) {
                                    $vv['fields'][$kkk] = explode(',', $vvv);
                                    $error[] = [
                                        'msg' => '扩展字段【' . $kkk . '】类型为多选，数据为非数组格式',
                                        'relation_id' => $v['id'],
                                        'data_id' => $vv['id'],
                                        'old' => $old_data,
                                        'new' => $vv['fields'],
                                        'model' => $model,
                                        'name' => $v['name']
                                    ];
                                }
                                if (in_array($fields[$kkk]['type'], [1, 3]) && !is_numeric($vvv)) {
                                    $vv['fields'][$kkk] = (int)(is_array($vvv) ? array_shift($vvv) : $vvv);
                                    $error[] = [
                                        'msg' => '扩展字段【' . $kkk . '】为下拉或单选，数据为非数字格式',
                                        'relation_id' => $v['id'],
                                        'data_id' => $vv['id'],
                                        'old' => $old_data,
                                        'new' => $vv['fields'],
                                        'model' => $model,
                                        'name' => $v['name']
                                    ];
                                }
                                if (in_array($fields[$kkk]['type'], [0, 4]) && !is_string($vvv)) {
                                    $vv['fields'][$kkk] = is_array($vvv) ? join('', $vvv) : '';
                                    $error[] = [
                                        'msg' => '扩展字段【' . $kkk . '】为单文本或文本域，数据为非字符串格式',
                                        'relation_id' => $v['id'],
                                        'data_id' => $vv['id'],
                                        'old' => $old_data,
                                        'new' => $vv['fields'],
                                        'model' => $model,
                                        'name' => $v['name']
                                    ];
                                }
                            }
                        }
                    }
                }
            }
        }
        return $error;
    }
}