<?php

declare(strict_types=1);

namespace App\Services\Reports\Formatters;

use App\Support\CsvFormulaGuard;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * XLSX через PhpSpreadsheet 5.x. Headers — bold + auto-size колонок.
 *
 * Quirk PhpSpreadsheet 5.x: метод setCellValueByColumnAndRow($col, $row, $val)
 * удалён (deprecated в 4.x → removed в 5.x). Используем A1-нотацию через
 * Coordinate::stringFromColumnIndex.
 *
 * F-CSV: опасные строки (ведущий = + - @) пишутся как явный текст
 * (setCellValueExplicit TYPE_STRING) — Excel НЕ вычисляет формулу. Числа
 * остаются числами.
 */
class XlsxFormatter implements ReportFormatter
{
    public function format(array $headers, array $rows): string
    {
        $spreadsheet = new Spreadsheet;
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Отчёт');

        // Headers (row 1, bold)
        foreach ($headers as $colIdx => $header) {
            $cell = $this->cellAddress($colIdx, 1);
            $sheet->setCellValue($cell, $header);
        }
        if (count($headers) > 0) {
            $lastCol = $this->cellAddress(count($headers) - 1, 1);
            $sheet->getStyle("A1:{$lastCol}")->getFont()->setBold(true);
        }

        // Data rows (row 2+)
        foreach ($rows as $rowIdx => $row) {
            foreach ($row as $colIdx => $value) {
                $cell = $this->cellAddress($colIdx, $rowIdx + 2);
                if (CsvFormulaGuard::isDangerous($value)) {
                    // formula-инъекция: пишем как явный текст, Excel не вычислит.
                    $sheet->setCellValueExplicit($cell, (string) $value, DataType::TYPE_STRING);
                } else {
                    $sheet->setCellValue($cell, $value);
                }
            }
        }

        // Auto-size всех колонок
        foreach (range(0, count($headers) - 1) as $colIdx) {
            $letter = $this->columnLetter($colIdx);
            $sheet->getColumnDimension($letter)->setAutoSize(true);
        }

        $writer = new Xlsx($spreadsheet);
        ob_start();
        $writer->save('php://output');
        $content = ob_get_clean();

        return $content === false ? '' : $content;
    }

    public function fileExtension(): string
    {
        return 'xlsx';
    }

    /**
     * 0 → A, 1 → B, ..., 25 → Z, 26 → AA, ...
     */
    private function columnLetter(int $colIdx): string
    {
        return Coordinate::stringFromColumnIndex($colIdx + 1);
    }

    private function cellAddress(int $colIdx, int $row): string
    {
        return $this->columnLetter($colIdx).$row;
    }
}
