<?php
declare(strict_types=1);

/**
 * 给 Action 提供 dxDataGrid CustomStore 对应的三个标准接口: grid / save / remove
 * 使用方在 Action 子类里 `use GridActions;` 并实现 gridModel() 即可
 */
trait GridActions
{
    /**
     * 返回当前控制器对应的 Model（必须是声明了 $table/$key 的 Model 实例）
     */
    abstract protected function gridModel(): Model;

    /**
     * 对应 CustomStore.load(loadOptions)
     */
    public function grid(): void
    {
        $this->success($this->gridModel()->grid($this->request));
    }

    /**
     * 对应 CustomStore.insert(values) / update(key, values)
     * 请求体: { key?: mixed, values: object }，有 key 是更新，没有 key 是新增
     */
    public function save(): void
    {
        $values = is_array($this->request['values'] ?? null) ? $this->request['values'] : [];
        $key = $this->request['key'] ?? null;

        if ($key !== null) {
            $this->gridModel()->gridUpdate($key, $values);
            $this->success(['key' => $key]);
        } else {
            $newKey = $this->gridModel()->gridInsert($values);
            $this->success(['key' => $newKey]);
        }
    }

    /**
     * 对应 CustomStore.remove(key)
     * 请求体: { key: mixed }
     */
    public function remove(): void
    {
        $this->gridModel()->gridRemove($this->request['key'] ?? null);
        $this->success();
    }

    /**
     * 通用 Excel 导出，对接前端 dxGrid.js 的"导出全部/导出已选"
     * 请求是表单 POST（不是 JSON body），columns/filter/keys 三个字段都是 JSON 字符串，这里手动解码
     * - columns: [{dataField, caption}, ...] 决定导出的列和表头，由前端传当前 dxDataGrid 的列配置
     * - keys: 传了就是"导出已选"，按主键 IN 这批 key 过滤
     * - filter: 没传 keys 时用，"导出全部"场景下是当前生效的过滤条件（DevExtreme filter 表达式）
     */
    public function export(): void
    {
        $columns = json_decode((string) ($this->request['columns'] ?? '[]'), true) ?: [];
        $model = $this->gridModel();

        $keys = isset($this->request['keys']) ? json_decode((string) $this->request['keys'], true) : null;
        if (is_array($keys)) {
            $filter = [$model->getKey(), 'anyof', $keys];
        } else {
            $filter = isset($this->request['filter']) ? json_decode((string) $this->request['filter'], true) : null;
        }

        $rows = $model->grid(['filter' => $filter])['data'];

        ExcelExporter::download($columns, $rows, $this->exportFileName());
    }

    /**
     * 导出文件名，默认用控制器类名，子类可覆盖（比如想用业务名称）
     */
    protected function exportFileName(): string
    {
        return 'export_' . date('YmdHis') . '.xlsx';
    }
}
