<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Tests\Export\Formatter;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\ExportGenerationContext;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\ExportManager;
use Chill\MainBundle\Export\Formatter\SpreadSheetFormatter;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Translation\TranslatableMessage;

/**
 * @internal
 *
 * @coversNothing
 */
class SpreadsheetFormatterTest extends TestCase
{
    use ProphecyTrait;

    public function testGenerate(): void
    {
        $translator = $this->prophesize(\Symfony\Contracts\Translation\TranslatorInterface::class);
        $translator->getLocale()->willReturn('en');
        $exportManager = $this->prophesize(ExportManager::class);

        $result =
            [
                ['export_count_activity' => 1, 'person_age' => 65, 'aggregator_some' => 'label0'], // row 0
            ];
        $exportAlias = 'count_activity_linked_to_person';
        $formatterData =
            ['format' => 'xlsx', 'person_age_aggregator' => ['order' => 1], 'aggregator2' => ['order' => 2]];
        $exportData = [];
        $filtersData =
            [
                'person_age_filter' => ['min_age' => 18, 'max_age' => 120, 'date_calc' => new RollingDate(RollingDate::T_TODAY)],
                'filter2' => [],
            ];
        $aggregatorsData =
            [
                'person_age_aggregator' => ['date_age_calculation' => new RollingDate(RollingDate::T_TODAY)],
                'aggregator2' => [],
            ];
        $context =
            new ExportGenerationContext($user = new User());

        $export = $this->prophesize(ExportInterface::class);
        $export->getTitle()->willReturn('Count activity linked to person');
        $translator->trans('Count activity linked to person')->willReturn('Count activity linked to person');
        $export->getQueryKeys($exportData)->willReturn(['export_count_activity']);
        $export->getLabels('export_count_activity', [1], $exportData)
            ->willReturn(fn (int|string $value): int|string => '_header' === $value ? 'Count activities' : $value);
        $translator->trans('Count activities')->willReturn('Count activities');
        $exportManager->getExport($exportAlias)->willReturn($export->reveal());

        $aggregator = $this->prophesize(\Chill\MainBundle\Export\AggregatorInterface::class);
        $aggregator->getTitle()->willReturn('Person age');
        $aggregator->getQueryKeys($aggregatorsData['person_age_aggregator'])->willReturn(['person_age']);
        $aggregator->getLabels('person_age', [65], $aggregatorsData['person_age_aggregator'])
            ->willReturn(fn (int|string $value): int|string => '_header' === $value ? 'Group by age' : $value);
        $translator->trans('Group by age')->willReturn('Group by age');
        $exportManager->getAggregator('person_age_aggregator')->willReturn($aggregator->reveal());

        $aggregator2 = $this->prophesize(\Chill\MainBundle\Export\AggregatorInterface::class);
        $aggregator2->getTitle()->willReturn(new TranslatableMessage('Some'));
        $aggregator2->getQueryKeys($aggregatorsData['aggregator2'])->willReturn(['aggregator_some']);
        $aggregator2->getLabels('aggregator_some', ['label0'], $aggregatorsData['aggregator2'])
            ->willReturn(fn (int|string $value): TranslatableMessage => new TranslatableMessage('_header' === $value ? 'Aggregator 2 header' : $value));
        $translator->trans('Aggregator 2 header', [], null, 'en')->willReturn('Aggregator 2 header');
        $translator->trans('label0', [], null, 'en')->willReturn('label0');
        $exportManager->getAggregator('aggregator2')->willReturn($aggregator2->reveal());

        $filter = $this->prophesize(\Chill\MainBundle\Export\FilterInterface::class);
        $filter->getTitle()->willReturn('Person by age');
        $filter->describeAction($filtersData['person_age_filter'], $context)
            ->willReturn(['Filter by age, from {{ start }} to {{ end }}', ['{{ start }}' => '18', '{{ end }}' => '120']]);
        $translator->trans('Filter by age, from {{ start }} to {{ end }}', ['{{ start }}' => '18', '{{ end }}' => '120'])
            ->willReturn('Filter by age, from 18 to 120');
        $exportManager->getFilter('person_age_filter')->willReturn($filter->reveal());

        $filter2 = $this->prophesize(\Chill\MainBundle\Export\FilterInterface::class);
        $filter2->getTitle()->willReturn(new TranslatableMessage('Some other filter'));
        $filter2->describeAction($filtersData['filter2'], $context)
            ->willReturn(new TranslatableMessage('Other filter description'));
        $translator->trans('Other filter description', [], null, 'en')
            ->willReturn('Some other filter description');
        $exportManager->getFilter('filter2')->willReturn($filter2->reveal());


        // create the formatter
        $formatter = new SpreadSheetFormatter($translator->reveal());
        $formatter->setExportManager($exportManager->reveal());

        $result = $formatter->generate(
            $result,
            $formatterData,
            $exportAlias,
            $exportData,
            $filtersData,
            $aggregatorsData,
            $context,
        );

        $tempFile = tempnam(sys_get_temp_dir(), 'test_spreadsheet_formatter_');
        file_put_contents($tempFile, $result->content);
        $spreadsheet = IOFactory::load($tempFile);
        $cells = $spreadsheet->getActiveSheet()->rangeToArray(
            'A1:G6',
            null,
            false,
            true,
            true,
        );
        unlink($tempFile);

        self::assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $result->contentType);
        self::assertEquals($cells[1], ['A' => 'Count activity linked to perso…', 'B' => null, 'C' => null, 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
        self::assertEquals($cells[2], ['A' => null, 'B' => null, 'C' => null, 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
        self::assertEquals($cells[3], ['A' => 'Filter by age, from 18 to 120', 'B' => null, 'C' => null, 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
        self::assertEquals($cells[4], ['A' => 'Some other filter description', 'B' => null, 'C' => null, 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
        self::assertEquals($cells[5], ['A' => 'Group by age', 'B' => 'Aggregator 2 header', 'C' => 'Count activities', 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
        self::assertEquals($cells[6], ['A' => 65, 'B' => 'label0', 'C' => 1, 'D' => null, 'E' => null, 'F' => null, 'G' => null]);
    }
}
