<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Rap2hpoutre\FastExcel\FastExcel;
use Illuminate\Support\Facades\Validator;

/**
 * @SWG\Swagger(
 *   basePath="/calculate-rates",
 *   @SWG\Info(
 *     title="项目名称 API",
 *     version="1.0.0"
 *   )
 * )
 */

class BaseController extends Controller
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
    use Tool;

    protected $model = '';  // 当前模型
    protected $fillable = [];  // 当前模型可以修改和新增的字段
    protected $resource = ''; // 显示个体资源
    protected $resourceCollection = ''; // 显示资源集合
    protected $map = [];   // 导入导出时候  数据表字段与说明的映射表


    public function index(Request $request)
    {
        // 显示订单列表
        $pageSize = $request->input('pageSize', 10);
        $this->log('select', '显示信息列表');
        return  $this->getListData($pageSize);
    }

    protected function getListData($pageSize)
    {
        // 当前列表数据  对应于原来的index
        $data = $this->model::paginate($pageSize);
        return new $this->resourceCollection($data);
    }


    public function show($id)
    {
        $data = $this->model::find($id);
        $this->log('select', '显示信息');
        return new $this->resource($data);
    }



    public function store(Request $request)
    {
//        1. 获取前端数据

        $data = $request->only($this->fillable);
//        2. 验证数据
        if (method_exists($this, 'message')) {
            $validator = Validator::make($data, $this->storeRule(), $this->message());
        } else {
            $validator = Validator::make($data, $this->storeRule());
        }
        if ($validator->fails()) {
            // 有错误，处理错误信息并且返回
            $errors = $validator->errors();
            $errorTips = '';
            foreach ($errors->all() as $message) {
                $errorTips = $errorTips.$message.',';
            }
            $errorTips = substr($errorTips, 0, strlen($errorTips)-1);
            return $this->errorWithInfo($errorTips, 422);
        }
//        3.数据无误，进一步处理后保存到数据表里面，有的表需要处理，有的不需要
        $data = $this->storeHandle($data);
        if ($this->model::create($data)) {
            $this->log('insert', '新增信息');
            return $this->successWithInfo('新增数据成功', 201);
        } else {
            return $this->error();
        }
    }

    protected function storeHandle($data)
    {
          return $data;   // TODO: Change the autogenerated stub
    }


    public function update(Request $request, $id)
    {
        $data = $request->only($this->fillable);
        if (method_exists($this, 'message')) {
            $validator = Validator::make($data, $this->updateRule($id), $this->message());
        } else {
            $validator = Validator::make($data, $this->updateRule($id));
        }
        if ($validator->fails()) {
            // 有错误，处理错误信息并且返回
            $errors = $validator->errors();
            $errorTips = '';
            foreach ($errors->all() as $message) {
                $errorTips = $errorTips.$message.',';
            }
            $errorTips = substr($errorTips, 0, strlen($errorTips)-1);
            return $this->errorWithInfo($errorTips, 422);
        }
        // 进一步处理数据
        $data = $this->updateHandle($data);
        // 更新到数据表
        if ($this->model::where('id', $id)->update($data)) {
            $this->log('update', '更新信息');
            return $this->successWithInfo('数据更新成功');
        } else {
            return $this->errorWithInfo('数据更新失败');
        }
    }

    protected function updateHandle($data)
    {
        return $data;
    }

    public function destroy($id)
    {
        if ($this->destoryHandle($id)) {
            $this->log('delete', '删除信息');
            return  $this->successWithInfo('数据删除成功', 204);
        } else {
            return $this->errorWithInfo('数据删除失败，请查看指定的数据是否存在');
        }
    }

    protected function destoryHandle($id)
    {
        DB::transaction(function () use ($id) {
            // 删除逻辑  注意多表关联的情况
            $this->model::where('id', $id)->delete();
        });
        return true;
    }

    public function deleteAll()
    {
        // 前端利用json格式传递数据
        $ids = json_decode(request()->input('ids'), true);
        foreach ($ids as $id) {
            $this->destoryHandle($id);
        }
        $this->log('delete', '删除多条信息');
        return $this->successWithInfo('批量删除数据成功', 204);
    }



    public function export()
    {
        $data = $this->model::all();
        $data = $data->toArray();
        $arr = $this->exportHandle($data);
        $data = collect($arr);
        $fileName = date('YmdHiS') . uniqid() .'.xlsx';
        $file = 'xls\\'.$fileName;
        (new FastExcel($data))->export($file);
        $this->log('export', '导出信息');
        return $this->successWithInfo($file);
    }

    protected function exportHandle($arrData)
    {
        // 默认会根据$map进行处理，
        $arr = [];
        foreach ($arrData as $item) {
            $tempArr = $this->handleItem($item, 'export');
            // 根据需要$tempArr可以进一步处理，特殊的内容，默认$tempArr是根据$this->map来处理
            $arr[] = $tempArr;
        }
        return $arr;
    }


    /**
     * 根据map表，处理数据
     * @param $data
     */
    protected function handleItem($data, $type = 'export')
    {
        $arr = [];
        if ($type === 'export') {
            foreach ($this->map as $key => $item) {
                if (!isset($data[$item])) {
                    continue;
                }
                $arr[$key] = $data[$item];
            }
        }
        if ($type === 'import') {
            foreach ($this->map as $key => $item) {
                if (!isset($data[$key])) {
                    continue;
                }
                $arr[$item] = $data[$key];
            }
        }
        return $arr;
    }


    public function import()
    {
//        1.接收文件，打开数据
//        2. 处理打开的数据，循环转换
//        3. 导入到数据库
        $data = (new FastExcel())->import(request()->file('file'));
        $arrData = $data->toArray();
        $arr = $this->importHandle($arrData);
        $this->model::insert($arr['successData']);
        $tips = '当前操作导入数据成功'.$arr['successCount'].'条';
        if ($arr['isError']) {
            // 有失败的数据，无法插入，要显示出来，让前端能下载
            $file = date('YmdHiS') . uniqid() .'.xlsx';
            $fileName = public_path('xls').'\\'.$file;
            $file = 'xls\\'.$file;
            $data = collect($arr['errorData']);
            (new FastExcel($data))->export($fileName);
            $tips .= ',失败'.$arr['errorCount'].'条';
            if ($arrData['successCount'] > 0) {
                $this->log('import', '导入信息');
            }
            return response()->json([
                'info' => $tips,
                'fileName' => $file,
                'status' => 'error',
                'status_code' => 422
            ], 422);
        } else {
            $this->log('import', '导入信息');
            return $this->successWithInfo($tips, 201);
        }
    }


    protected function validatorData($item, $data, &$error, &$isError, &$successCount, &$errorCount, &$arr)
    {
        if (method_exists($this, 'message')) {
            $validator = Validator::make($data, $this->storeRule(), $this->message());
        } else {
            $validator = Validator::make($data, $this->storeRule());
        }
        if ($validator->fails()) {
            // 获取相关的错误信息，并且把错误信息单独存放
            $errors = $validator->errors($validator);
            $tips = '';
            foreach ($errors->all() as $message) {
                $tips .= $message.',';
            }
            $tips = substr($tips, 0, strlen($tips)-1);
            // 状态信息
            $item['错误原因'] = $tips;
            $error[] = $item;
            $isError = true;
            $errorCount ++;
        } else {
            // 没有出错的，我们先存在正确的数组
            $arr[] = $data;
            $successCount ++;
        }
    }


    protected function storeRule()
    {
        return [];
    }

    protected function UpdateRule($id)
    {
        return [];
    }


    protected function  message(){
        return [];
    }
}
