<?php
// 这是系统自动生成的公共文件

if (!function_exists('xlsx_reader')) {
    /**
     * 读取Excel数据
     * @param string $file Excel文件路径
     * @param int $initial_row 初始行
     * @param array $keys_map 列 -> 键 例：['A' => 'name', 'B' => 'age', 'C' => 'sex']
     * @return array
     */
    function xlsx_reader(string $file, int $initial_row = 1, array $keys_map = []): array
    {
        $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');

        // 读取文件
        $spreadsheet = $reader->load($file);

        // 获取活动sheet
        $sheet = $spreadsheet->getActiveSheet();

        // 获取最大行
        $max_row = $sheet->getHighestRow();

        // 获取最大列
        $max_col = $sheet->getHighestColumn();

        $xlsx_data = [];
        $first_col = ord('A');
        $last_col  = ord($max_col);
        for ($row = $initial_row; $row <= $max_row; $row++) {
            for ($col = $first_col; $col <= $last_col; $col++) {
                $key = $col_chr = chr($col);
                if (!empty($keys_map)) {
                    $key = $keys_map[$col_chr] ?? $col_chr;
                }
                $xlsx_data[$row][$key] = $sheet->getCell($col_chr . $row)->getValue();
            }
        }

        return $xlsx_data;
    }
}

if (!function_exists('xlsx_writer')) {
    /**
     * 构建Excel数据
     * @param array $data 数据 例：[['name'=>'张三','age'=>18, 'sex'=>'男']]
     * @param array $schema 表头信息 例：['name' => '姓名', 'age' => '年龄', 'sex' => '性别']
     * @param string $filename 下载文件名称 默认为YmdHis时间
     * @param string $output 输出方式 php://output 或 文件路径
     * @return \think\Response
     */
    function xlsx_writer(array|\think\model\Collection $data, array $schema, string $filename = '', string $output = 'php://output'): \think\Response
    {
        // 获取Spreadsheet对象
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 写入表头
        $title = array_values($schema);
        $title_col = 'A';
        foreach ($title as $value) {
            // 单元格内容写入
            $sheet->setCellValue($title_col . '1', $value);
            $title_col++;
        }

        // 写入数据
        $row = 2;
        $keys = array_keys($schema);
        foreach ($data as $item) {
            $data_col = 'A';
            foreach ($keys as $key) {
                $sheet->setCellValue($data_col . $row, $item[$key] ?? '');
                $data_col++;
            }
            $row++;
        }

        flush();
        ob_flush();
        if ($filename == '') $filename = date('YmdHis');
        $filename = urlencode($filename);
        // 文件写入缓冲区
        \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx')->save($output);
        // 从缓冲区获取导出文件，并通过Response返回（解决thinkphp框架的Response无法获取设置的header问题）
        $file_data = ob_get_clean();
        $response  = \think\Response::create($file_data)->header([
            'Access-Control-Expose-Headers' => 'Content-Disposition',
            'Content-Type'                  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8',
            'Content-Disposition'           => 'attachment;filename=' . $filename . '.xlsx',
            'Cache-Control'                 => 'max-age=0'
        ]);
        return $response;
    }
}

if (!function_exists('strtobytes')) {

    /**
     * 字符串转字节
     * @param string $str_size 字符串 例：'1MB' '2GB'
     * @return int
     */
    function strtobytes(string $str_size): int
    {
        preg_match('/(\d+)(\w+)/', $str_size, $matches);
        if (!isset($matches[1])) {
            throw new \Exception('请确认size大小');
        }
        if (!isset($matches[2])) {
            throw new \Exception('请确认单位');
        }

        $size = intval($matches[1]);
        $unit = $matches[2];
        switch (strtolower($unit)) {
            case 'kb':
                $size *= 1024;
                break;
            case 'mb': 
                $size *= 1024 * 1024;
                break;
            case 'gb': 
                $size *= 1024 * 1024 * 1024;
                break;
            case 'tb':
                $size *= 1024 * 1024 * 1024 * 1024;
            default: 
                throw new \Exception('不支持[' . $unit . ']单位');
        }
        return $size;
    }
}