<?php

namespace Ignite\Core\Tests\Unit\Files;

use Ignite\Core\Files\CsvFileGenerator;
use Ignite\Core\Files\File;
use Ignite\Core\Files\Processors\AdhocFileProcessor;
use Ignite\Core\Files\TemporaryFile;
use Ignite\Core\Tests\Support\Exports\SimpleExport;
use Ignite\Core\Tests\TestCase;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;

class CsvFileGeneratorTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        Storage::fake();
    }

    /** @test */
    public function generates_a_temporary_csv_file_by_default()
    {
        // Execute
        $file = (new CsvFileGenerator(new SimpleExport()))->generate();

        // Check
        $this->assertInstanceOf(TemporaryFile::class, $file);
        $this->assertCount(3, $this->createReaderFromStream($file->readStream())->getRecords());
        $this->assertEquals('first-last-email-phone', join('-', fgetcsv($file->readStream())));
    }

    /** @test */
    public function can_specify_a_place_to_save_the_generated_file()
    {
        // Arrange
        $destinationFile = new File('my-generated-file.csv');
        $csvFileGenerator = (new CsvFileGenerator(new SimpleExport()))->destination($destinationFile);

        // Execute
        $generatedFile = $csvFileGenerator->generate();

        // Check
        $this->assertInstanceOf(File::class, $generatedFile);
        $this->assertNotInstanceOf(TemporaryFile::class, $generatedFile);
        $this->assertTrue($destinationFile->is($generatedFile));
        $this->assertCount(3, $this->createReaderFromStream($generatedFile->readStream())->getRecords());
    }

    /** @test */
    public function can_add_encryption_to_the_generated_file()
    {
        // Arrange
        $csvFileGenerator = (new CsvFileGenerator(new SimpleExport()))->addEncryption();

        // Execute
        $generatedFile = $csvFileGenerator->generate();

        // Check
        $this->assertInstanceOf(TemporaryFile::class, $generatedFile);
        $this->assertCount(3, $this->createReaderFromString($generatedFile->decrypt()->get())->getRecords());
    }

    /** @test */
    public function can_add_processors()
    {
        // Arrange
        $csvFileGenerator = (new CsvFileGenerator(new SimpleExport()));

        // Execute
        $generatedFile = $csvFileGenerator
            ->addProcessor(new AdhocFileProcessor(function (File $file) {
                $file->put('altered file contents');
                return $file;
            }))
            ->addProcessor(new AdhocFileProcessor(function (File $file) {
                $file->append('other contents');
                return $file;
            }))
            ->addProcessor(function (File $file) {
                $file->append('more content');
                return $file;
            })
            ->generate();

        // Check
        $this->assertEquals("altered file contents\nother contents\nmore content", $generatedFile->get());
    }

    protected function createReaderFromStream($stream): Reader
    {
        // createFromStream() is deprecated since league/csv:9.27.0
        if (method_exists(Reader::class, 'from')) {
            return Reader::from($stream);
        }

        return Reader::createFromStream($stream);
    }

    protected function createReaderFromString(string $contents): Reader
    {
        // createFromString() is deprecated since league/csv:9.27.0
        if (method_exists(Reader::class, 'fromString')) {
            return Reader::fromString($contents);
        }

        return Reader::createFromString($contents);
    }
}
