<?php

namespace FilterTest;

use KupShop\KupShopBundle\Config;
use PHPUnit\DbUnit\DataSet\YamlDataSet;

class FilterParametersTest extends \DatabaseTestCase
{
    private $param = [
        'color' => 2,
        'size' => 1,
        'size2' => 3,
        'descr' => 4,
    ];

    private $paramValue = [
        'black' => 1,
        'white' => 2,
    ];

    /** @var \Filter */
    private $filter;

    /** @var \FilterParams */
    private $filterParams;

    public function setUp(): void
    {
        parent::setUp();

        $cfg = Config::get();
        $cfg['Modules']['indexed_filter'] = false;

        $this->filter = new \Filter();
        $this->filterParams = new \FilterParams();
        $this->filterParams->setSections([1, 2]);
        $this->filter->setFilterParams($this->filterParams);
    }

    public function testFiltersDeepBySectionOnly()
    {
        $producers = $this->filter->getProducers()['values'];

        $this->assertCount(2, $producers);

        $this->assertArrayHasKey(1, $producers);
        $this->assertEquals(3, $producers[1]['count']);
        $this->assertSame('Producer 1', $producers[1]['name']);

        $this->assertArrayHasKey(2, $producers);
        $this->assertEquals(1, $producers[2]['count']);
        $this->assertSame('Producer 2', $producers[2]['name']);
    }

    /**
     * @dataProvider dataSet_testSectionAndParameters
     */
    public function testSectionAndParameters(array $params, array $expectedProducersValuesArray)
    {
        foreach ($params as $param) {
            $this->filterParams->setParameter($param[0], $param[1], $param[2]);
        }

        $producersValuesArray = $this->filter->getProducers()['values'];

        $this->assertEquals($expectedProducersValuesArray, $producersValuesArray);
    }

    public function dataSet_testSectionAndParameters()
    {
        return [
            [
                [
                    [$this->param['color'], [$this->paramValue['black']], \Filter::PARAM_LIST],
                ],
                [1 => ['id' => '1', 'name' => 'Producer 1', 'photo' => 'x.jpg', 'count' => '2']],
            ],
            [
                [
                    [$this->param['color'], [$this->paramValue['white']], \Filter::PARAM_LIST],
                ],
                [],
            ],
            [
                [
                    [$this->param['color'], [$this->paramValue['black'], $this->paramValue['white']], \Filter::PARAM_LIST],
                ],
                [1 => ['id' => '1', 'name' => 'Producer 1', 'photo' => 'x.jpg', 'count' => '2']],
            ],
            [
                [
                    [$this->param['color'], [$this->paramValue['black']], \Filter::PARAM_LIST],
                    [$this->param['size'], ['min' => 5, 'max' => 5], \Filter::PARAM_INT],
                ],
                [1 => ['id' => '1', 'name' => 'Producer 1', 'photo' => 'x.jpg', 'count' => '1']],
            ],
        ];
    }

    public function testTranslateParameters()
    {
        $this->switchLanguage();

        $parameter = $this->filter->getParameter($this->param['color'], \Filter::PARAM_LIST);

        $expected = [
            'param_name' => 'Farba',
            'values' => [
                '1' => [
                    'id' => '1',
                    'param_name' => 'Farba',
                    'name' => 'čierna',
                    'description' => 'čierna desc',
                    'count' => '2',
                    'position' => 2,
                    'unit' => '',
                    'data' => [],
                ],
            ],
        ];

        $this->assertEquals($expected, $parameter);
    }

    /**
     * @dataProvider dataSet_testGetParameter
     */
    public function testGetParameterCountsProducts($paramId, $paramType, $expectedResult)
    {
        $parameter = $this->filter->getParameter($paramId, $paramType);
        $this->assertEquals($expectedResult, $parameter, '', 0.0, 10, true);
    }

    public function dataSet_testGetParameter()
    {
        $result[] = [
            $this->param['color'],
            \Filter::PARAM_LIST,
            [
                'param_name' => 'Color',
                'values' => [
                    '1' => [
                        'id' => '1',
                        'param_name' => 'Color',
                        'name' => 'black',
                        'description' => 'black descr',
                        'count' => '2',
                        'unit' => '',
                        'data' => [],
                        'position' => 2,
                    ],
                ],
            ],
        ];
        $result[] = array_merge_strict(end($result), [
            3 => ['values' => ['1' => ['count' => '3']]],
        ]);

        $result[] = [
            $this->param['size'],
            \Filter::PARAM_INT,
            [
                'param_name' => 'Size',
                'values' => [
                    'min' => '5',
                    'max' => '10',
                ],
            ],
        ];

        $result[] = [
            $this->param['size2'],
            \Filter::PARAM_INT,
            [
                'param_name' => 'Size2',
                'values' => null,
            ],
        ];

        $result[] = [
            $this->param['descr'],
            \Filter::PARAM_CHAR,
            [
                'param_name' => 'Descr',
                'values' => [
                    'Popisek' => [
                        'id' => 'Popisek',
                        'param_name' => 'Descr',
                        'name' => 'Popisek',
                        'count' => '2',
                        'unit' => '',
                    ],
                ],
            ],
        ];

        return $result;
    }

    public function testSetFilterData()
    {
        $filterData = [
            'producerIds' => [1, 2, 3],
            'campaigns' => ['A', 'B', 'C'],
            'inStore' => 42,
            'inSupplier' => 42,
            'price' => [
                'min' => 5,
                'max' => 500,
                'value' => '4,5-100',
            ],
            'parameters' => [
                5 => [
                    'value' => '6 - 8',
                    'min' => 5,
                    'max' => 10,
                    'type' => 'int',
                ],
                10 => [
                    'value' => [7, 8, 9],
                    'type' => 'list',
                ],
            ],
            'variations' => [
                10 => [
                    'value' => [50, 100],
                ],
            ],
            'sectionIDsFilter' => [3, 4],
        ];

        $expected = [
            'sectionIds' => [1, 2],
            'sectionIdsFilter' => [3, 4],
            'variations' => [10 => [50, 100]],
            'producers' => [1, 2, 3],
            'parameters' => [
                5 => ['values' => ['min' => 6.0, 'max' => 8.0], 'type' => 'int'],
                10 => ['values' => [7, 8, 9], 'type' => 'list'],
            ],
            'inStore' => \Filter::IN_STORE_SUPPLIER,
            'priceRange' => new \Range(null, 100),
            'campaigns' => ['A', 'B', 'C'],
            'invertParameters' => [],
            'relatedProducts' => [],
            'stores' => [],
            'variationsSizeConvertion' => [],
            'labels' => [],
            'inSale' => null,
            'productCodes' => [],
            'andParameters' => [],
            'search' => null,
            'products' => [],
            'quantityDiscounts' => [],
            'showInSearch' => false,
        ];

        $this->filter->setFilterData($filterData);
        $this->assertEquals($expected, $this->filterParams->getParams());
    }

    public function getDataset()
    {
        return new YamlDataSet(__DIR__.'/FilterParametersTest.yml');
    }
}
