<?php

declare(strict_types=1);

namespace app\admin\controller\v1;

use app\admin\model\v1\SysConfigGroupModel;
use app\admin\model\v1\SysConfigModel;

/**
 * 站酷配置控制器
 */
class SiteConfig
{
    // 获取配置项
    public function index()
    {
        // 按语言获取分组
        $groups = SysConfigGroupModel::field([
                'id',
                'name'
            ])
            ->language(request()->lang_id)
            ->enabled()
            ->order(['sort' => 'asc', 'id' => 'desc'])
            ->select()
            ->toArray();
        if (empty($groups)) {
            return error('配置分组不存在');
        }

        // 根据分组获取配置项
        $configs = SysConfigModel::field([
                'id',
                'group_id',
                'title',
                'name',
                'value',
                'extra',
                'type',
                'remark'
            ])
            ->groupId(array_column($groups, 'id'))
            ->order(['sort' => 'asc', 'id' => 'desc'])
            ->select()
            ->each(function ($item) {
                // 修改字段为null的输出为空字符串
                $keys = array_keys($item->toArray());
                foreach ($keys as $key) {
                    if (is_null($item[$key])) {
                        $item[$key] = '';
                    }
                }
                return $item;
            })
            ->toArray();

        // 处理附加配置项及联动项
        $configs = $this->handleExtra($configs);

        // 组合数据
        $config_group_map = [];
        foreach ($configs as $config) {
            $group_id = $config['group_id'];
            unset($config['group_id']);
            $config_group_map[$group_id][] = $config;
        }

        // 组合分组和配置项
        foreach ($groups as &$group) {
            $group['configs'] = $config_group_map[$group['id']] ?? [];
        }
        unset($group);

        return success('获取成功', $groups);
    }
    // 处理配置联动项数据
    private function handleExtra($data)
    {
        list($list, $map) = $this->parseExtra($data);
        return $this->buildExtra($list, $map);
    }
    private function parseExtra($data)
    {
        $linkage_names = [];
        foreach ($data as &$val) {
            if (!empty($val['extra'])) {
                $extra = explode(PHP_EOL, $val['extra']);
                $val['extra'] = [];
                foreach ($extra as $v) {
                    if (preg_match('/^([^:]+):(.*?)(?:\[(.*?)\])?$/i', trim($v), $match)) {
                        $item = [
                            'name'          => $match[2],
                            'value'         => $match[1],
                            'linkage_names' => [],
                        ];
                        if (isset($match[3])) {
                            $item['linkage_names'] = array_map(function ($it) {
                                return str_replace(['"', "'"], '', trim($it));
                            }, explode(',', $match[3]));
                        }
                        $linkage_names = array_merge($linkage_names, $item['linkage_names']);
                        $val['extra'][] = $item;
                    }
                }
            }
        }
        unset($val);

        $linkage_data = [];
        foreach ($data as $key => $val) {
            if (in_array($val['name'], $linkage_names)) {
                $linkage_data[$val['name']] = $val;
                unset($data[$key]);
            }
        }

        return [$data, $linkage_data];
    }
    private function buildExtra($data, $linkage_data)
    {
        $ret = [];
        foreach ($data as $val) {
            if (!empty($val['extra'])) {
                foreach ($val['extra'] as &$v) {
                    $linkage_names = $v['linkage_names'];
                    unset($v['linkage_names']);
                    $children = [];
                    foreach ($linkage_names as $name) {
                        if (!empty($linkage_data[$name])) {
                            $children[] = $linkage_data[$name];
                        }
                    }
                    $v['children'] = $this->handleExtra($children);
                }
                unset($v);
            }
            $ret[] = $val;
        }

        return $ret;
    }

    // 根据分组获取配置
    public function getByGroupUniqueLabel($unique_label)
    {
        $configs = SysConfigModel::alias('c')
            ->field([
                'c.id',
                'c.title',
                'c.name',
                'c.value',
            ])
            ->join(SysConfigGroupModel::getTable(). ' g', 'g.id = c.group_id')
            ->where('g.language_id', '=', request()->lang_id)
            ->where('g.unique_label', '=', $unique_label)
            ->where('g.status', '=', 1)
            ->order(['c.sort' => 'asc', 'c.id' => 'desc'])
            ->select()
            ->each(function ($item) {
                // 修改字段为null的输出为空字符串
                $keys = array_keys($item->toArray());
                foreach ($keys as $key) {
                    if (is_null($item[$key])) {
                        $item[$key] = '';
                    }
                }
                return $item;
            })
            ->toArray();
        if (!empty($configs)) {
            $configs_map = [];
            foreach ($configs as $cfg) {
                $current = &$configs_map;
                
                // 根据name中"."拆分为多维数组
                $parts = explode('.', $cfg['name']);
                foreach ($parts as $part) {
                    if (!isset($current[$part])) {
                        $current[$part] = [];
                    }
                    $current = &$current[$part];
                }
                $current = [
                    'id'    => $cfg['id'],
                    'title' => $cfg['title'],
                    'name'  => $cfg['name'],
                    'value' => $cfg['value']
                ];
            }
            unset($current);

            return $configs_map;
        }

        return [];
    }

    // 更新配置
    public function update()
    {
        $put = request()->put();

        if (empty($put)) {
            return error('参数错误');
        }

        $validate = \think\facade\Validate::rule([
                'id'    => 'require|integer',
                'value' => 'max:5120'
            ])
            ->message([
                'id.require'    => '配置项ID不能为空',
                'id.integer'    => '配置项ID必须是整数',
                'value.max'     => '配置值不能超过5120个字符'
            ]);
        foreach ($put as $val) {
            if (!$validate->check($val)) {
                return error($validate->getError());
            }
        }

        $configs = (new SysConfigModel)->saveAll($put);
        if ($configs->isEmpty()) {
            return error('操作失败');
        }

        return success('操作成功');
    }
}
