<?php
declare(strict_types=1);

use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * 通用 dxDataGrid -> Excel 导出，配合 GridActions::export() 使用
 */
final class ExcelExporter
{
    /**
     * @param array $columns [{dataField, caption}, ...]，决定导出哪些列、表头文字、列的先后顺序
     * @param array $rows 数据行，每行是关联数组
     * @param string $filename 下载文件名
     */
    public static function download(array $columns, array $rows, string $filename): void
    {
        if (!$columns) {
            throw new MvcException('导出失败：未指定导出列');
        }

        $rows = self::applyLookups($columns, $rows);

        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        $col = 1;
        foreach ($columns as $column) {
            $sheet->setCellValue([$col, 1], $column['caption'] ?? $column['dataField']);
            $col++;
        }

        $rowIndex = 2;
        foreach ($rows as $row) {
            $col = 1;
            foreach ($columns as $column) {
                $field = $column['dataField'] ?? '';
                $sheet->setCellValue([$col, $rowIndex], $row[$field] ?? '');
                $col++;
            }
            $rowIndex++;
        }

        foreach (range(1, count($columns)) as $col) {
            $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
        }

        $lastCol = Coordinate::stringFromColumnIndex(count($columns));
        $lastRow = max(1, $rowIndex - 1);
        $headerRange = "A1:{$lastCol}1";

        $sheet->getStyle($headerRange)->getFont()->setBold(true)->getColor()->setRGB('FFFFFF');
        $sheet->getStyle($headerRange)->getFill()
            ->setFillType(Fill::FILL_SOLID)
            ->getStartColor()->setRGB('2A3C63');
        $sheet->setAutoFilter("A1:{$lastCol}{$lastRow}");

        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        (new Xlsx($spreadsheet))->save('php://output');
        exit;
    }

    /**
     * 把带 lookup 的列（比如部门下拉）从原始值（如 admin_lnk_depa_id）替换成当前显示名称，
     * 跟前端 dxDataGrid 的 columns[].lookup 配置（dataSource/valueExpr/displayExpr）保持一致，
     * 对任何 lookup 列通用，不针对某个具体业务字段
     */
    private static function applyLookups(array $columns, array $rows): array
    {
        foreach ($columns as $column) {
            $lookup = $column['lookup'] ?? null;
            $field = $column['dataField'] ?? '';
            if (!$lookup || $field === '' || !is_array($lookup['dataSource'] ?? null)) {
                continue;
            }

            $valueExpr = $lookup['valueExpr'] ?? 'this';
            $displayExpr = $lookup['displayExpr'] ?? 'this';

            $map = [];
            foreach ($lookup['dataSource'] as $item) {
                if (is_array($item) && array_key_exists($valueExpr, $item)) {
                    $map[$item[$valueExpr]] = $item[$displayExpr] ?? $item[$valueExpr];
                }
            }

            foreach ($rows as &$row) {
                if (isset($row[$field]) && array_key_exists($row[$field], $map)) {
                    $row[$field] = $map[$row[$field]];
                }
            }
            unset($row);
        }

        return $rows;
    }
}
