<?php

declare(strict_types=1);

namespace Tvdt\Service;

use PhpOffice\PhpSpreadsheet\Reader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer;
use Symfony\Component\HttpFoundation\File\File;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Exception\SpreadsheetDataException;

class QuizSpreadsheetService
{
    public function generateTemplate(bool $fillExample = true): \Closure
    {
        $spreadsheet = new Spreadsheet();

        $sheet = $spreadsheet->getActiveSheet();

        $sheet->getStyle('1:1')->getFont()->setBold(true);

        $sheet->setCellValue('A1', 'Question');
        $sheet->getColumnDimension('A')->setWidth(30);
        $sheet->getStyle('A:A')->getAlignment()->setWrapText(true);

        $counter = 1;
        foreach (range('B', 'L', 2) as $column) {
            $sheet->setCellValue($column.'1', 'Answer '.$counter++);
            $sheet->getColumnDimension($column)->setWidth(30);
            $sheet->getStyle($column.':'.$column)->getAlignment()->setWrapText(true);
        }

        foreach (range('C', 'M', 2) as $column) {
            $sheet->setCellValue($column.'1', 'Correct');
            $sheet->getColumnDimension($column)->setAutoSize(true);
        }

        if ($fillExample) {
            $sheet->setCellValue('B2', 'Man');
            $sheet->setCellValue('C2', true);

            $sheet->setCellValue('D2', 'Vrouw');
            $sheet->setCellValue('E2', false);

            $sheet->setCellValue('A2', 'Is de mol een man of een vrouw?');
        }

        return $this->toXlsx($spreadsheet);
    }

    /** @throws SpreadsheetDataException */
    public function xlsxToQuiz(Quiz $quiz, File $file): void
    {
        if (!$this->isSpreadsheetFile($file)) {
            throw new \InvalidArgumentException('File must be a valid XLSX spreadsheet');
        }

        $spreadsheet = $this->readSheet($file);
        $sheet = $spreadsheet->getSheet($spreadsheet->getFirstSheetIndex());

        $answerLines = \array_slice($sheet->toArray(formatData: false), 1);

        $this->fillQuizFromArray($quiz, $answerLines);
    }

    private function readSheet(File $file): Spreadsheet
    {
        return new Reader\Xlsx()->setReadDataOnly(true)->load($file->getRealPath());
    }

    /**
     * @param array<int, array<int, string|bool|null>> $sheet
     *
     * @throws SpreadsheetDataException
     */
    private function fillQuizFromArray(Quiz $quiz, array $sheet): void
    {
        $errors = [];

        $questionCounter = 1;
        foreach ($sheet as $questionArr) {
            if (null === $questionArr[0]) {
                break;
            }

            $question = new Question();
            $question->question = (string) $questionArr[0];
            $question->ordering = $questionCounter++;

            $answerCounter = 1;
            $arrCounter = 1;

            while (true) {
                if (null === $questionArr[$arrCounter]) {
                    if (1 === $answerCounter) {
                        $errors[] = \sprintf('Question %d has no answers', $answerCounter);
                    }

                    break;
                }

                $answer = new Answer((string) $questionArr[$arrCounter++], (bool) $questionArr[$arrCounter++]);
                $answer->ordering = $answerCounter++;
                $question->addAnswer($answer);
            }

            $quiz->addQuestion($question);
        }

        if ([] !== $errors) {
            throw new SpreadsheetDataException($errors);
        }
    }

    public function quizToXlsx(Quiz $quiz): void
    {
        throw new \Exception('Not implemented');
    }

    private function toXlsx(Spreadsheet $spreadsheet): \Closure
    {
        $writer = new Writer\Xlsx($spreadsheet);

        return static fn () => $writer->save('php://output');
    }

    private function isSpreadsheetFile(File $file): bool
    {
        return 'xlsx' === $file->getExtension();
    }
}
