<?php
declare(strict_types=1);

namespace FCA\StockApi\Document;

use FCA\StockApi\Exception\ApiException;

class Offer extends Base
{
    /**
     * @var int
     */
    protected $id;

    /**
     * @var Offer\Brand
     */
    protected $brand;

    /**
     * @var Offer\Model
     */
    protected $model;

    /**
     * @var Offer\Version
     */
    protected $version;

    /**
     * @var Offer\Series
     */
    protected $series;

    /**
     * @var Offer\Dealer|null
     */
    protected $dealer;

    /**
     * @var string
     */
    protected $status;

    /**
     * @var Offer\Price
     */
    protected $price;

    /**
     * @var bool
     */
    protected $isDemo;

    /**
     * @var int
     */
    protected $productionYear;

    /**
     * @var string|null
     */
    protected $productionDate;

    /**
     * @var string
     */
    protected $sincom;

    /**
     * @var string[]
     */
    protected $stamps;

    /**
     * @var Offer\Color
     */
    protected $color;

    /**
     * @var Offer\Interior
     */
    protected $interior;

    /**
     * @var null|string
     */
    protected $description;

    /**
     * @var string
     */
    protected $serialNo;

    /**
     * @var string[]
     */
    protected $labels;

    /**
     * @var array
     */
    protected $images;

    /**
     * @var Offer\Equipment[]
     */
    protected $equipment = [];

    /**
     * @var Offer\TechnicalData
     */
    protected $technicalData;

    /**
     * @var array
     */
    protected $groups = [];

    /**
     * @var array
     */
    protected $financing = [];

    /**
     * Offer constructor.
     * @param $offer
     * @throws ApiException
     */
    public function __construct($offer)
    {
        $requiredKeys = [
            'vehicle_id',
            'brand',
            'model',
            'version',
            'series',
            'dealer',
            'status',
            'price',
            'is_demo',
            'year_of_production',
            'date_of_production',
            'color',
            'interior',
            'description',
            'serial_no',
            'images',
            'labels',
            'equipment',
            'technical_data',
            'sincom',
            'stamps',
            'financing',
        ];

        $this->checkKeys($requiredKeys, $offer);

        $this->id = $offer['vehicle_id'];
        $this->brand = new Offer\Brand($offer['brand']['code'], $offer['brand']['name'], $offer['brand']['slug']);
        $this->model = new Offer\Model(
            $offer['model']['code'],
            $offer['model']['commercial_code'],
            $offer['model']['name'],
            (array)$offer['model']['groups']
        );
        $this->version = new Offer\Version(
            $offer['version']['code'],
            $offer['version']['commercial_code'],
            $offer['version']['name'],
            $offer['version']['slug'],
            (float)$offer['version']['price']
        );
        $this->series = new Offer\Series($offer['series']['code'], $offer['series']['special_code']);

        if ($offer['dealer'] !== null) {
            $this->dealer = new Offer\Dealer((array)$offer['dealer']);
        } else {
            $this->dealer = null;
        }

        $this->status = $offer['status'];
        $this->price = new Offer\Price(
            $offer['price']['base']['netto'],
            $offer['price']['base']['brutto'],
            $offer['price']['final']['netto'],
            $offer['price']['final']['brutto']
        );
        $this->isDemo = (bool) $offer['is_demo'];
        $this->productionYear = (int) $offer['year_of_production'];
        $this->productionDate = $offer['date_of_production'];
        $this->sincom = $offer['sincom'];
        $this->stamps = (array)$offer['stamps'];
        $this->color = new Offer\Color(
            $offer['color']['code'],
            $offer['color']['name'],
            $offer['color']['category'],
            $offer['color']['type']
        );
        $this->interior = new Offer\Interior(
            $offer['interior']['code'],
            $offer['interior']['name'],
            $offer['interior']['type']
        );
        $this->description = $offer['description'];
        $this->serialNo = $offer['serial_no'];
        $this->images = (array)$offer['images'];
        $this->labels = (array)$offer['labels'];
        $this->financing = (array)$offer['financing'];

        foreach ($offer['equipment'] as $equipment) {
            $this->equipment[] = new Offer\Equipment(
                $equipment['code'],
                $equipment['type'],
                $equipment['name'],
                (float) $equipment['price']
            );
        }

        $this->technicalData = new Offer\TechnicalData((array)$offer['technical_data']);

        if (isset($offer['groups'])) {
            $this->groups = (array)$offer['groups'];
        }
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getBrand(): Offer\Brand
    {
        return $this->brand;
    }

    public function getModel(): Offer\Model
    {
        return $this->model;
    }

    public function getVersion(): Offer\Version
    {
        return $this->version;
    }

    public function getSeries(): Offer\Series
    {
        return $this->series;
    }

    public function getDealer(): ?Offer\Dealer
    {
        return $this->dealer;
    }

    public function getStatus(): string
    {
        return $this->status;
    }

    public function getPrice(): Offer\Price
    {
        return $this->price;
    }

    public function getIsDemo(): bool
    {
        return $this->isDemo;
    }

    public function getProductionYear(): int
    {
        return $this->productionYear;
    }

    public function getProductionDate(): ?string
    {
        return $this->productionDate;
    }

    public function getSincom(): string
    {
        return $this->sincom;
    }

    /**
     * @return string[]
     */
    public function getStamps(): array
    {
        return $this->stamps;
    }

    public function getColor(): Offer\Color
    {
        return $this->color;
    }

    public function getInterior(): Offer\Interior
    {
        return $this->interior;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function getSerialNo(): string
    {
        return $this->serialNo;
    }

    public function getImages(): array
    {
        return $this->images;
    }

    /**
     * @return string[]
     */
    public function getLabels(): array
    {
        return $this->labels;
    }

    /**
     * @return Offer\Equipment[]
     */
    public function getEquipment(): array
    {
        return $this->equipment;
    }

    public function getTechnicalData(): Offer\TechnicalData
    {
        return $this->technicalData;
    }

    public function getGroups(): array
    {
        return $this->groups;
    }

    public function getFinancing(): array
    {
        return $this->financing;
    }

    private function getEquipmentArray(): array
    {
        $equipment_set = [];

        foreach ($this->getEquipment() as $equipment) {
            $equipment_set[] = $equipment->toArray();
        }

        return $equipment_set;
    }

    public function toArray(): array
    {
        return [
            'id' => $this->getId(),
            'brand' => $this->getBrand()->toArray(),
            'model' => $this->getModel()->toArray(),
            'version' => $this->getVersion()->toArray(),
            'series' => $this->getSeries()->toArray(),
            'dealer' => is_null($this->getDealer()) ? null : $this->getDealer()->toArray(),
            'status' => $this->getStatus(),
            'price' => $this->getPrice()->toArray(),
            'isDemo' => $this->getIsDemo(),
            'productionYear' => $this->getProductionYear(),
            'productionDate' => $this->getProductionDate(),
            'sincom' => $this->getSincom(),
            'stamps' => $this->getStamps(),
            'color' => $this->getColor()->toArray(),
            'interior' => $this->getInterior()->toArray(),
            'description' => $this->getDescription(),
            'serialNo' => $this->getSerialNo(),
            'images' => $this->getImages(),
            'labels' => $this->getLabels(),
            'equipment' => $this->getEquipmentArray(),
            'technicalData' => $this->getTechnicalData()->toArray(),
            'groups' => $this->getGroups(),
            'financing' => $this->getFinancing(),
        ];
    }

    public function toSimpleArray(): array
    {
        $dealer = $this->getDealer();
        $price = $this->getPrice();
        $images = $this->getImages();

        return [
            'id' => $this->getId(),
            'brand' => $this->getBrand()->getName(),
            'localization' => $dealer ? 'woj. ' . $dealer->getRegion() . ', ' . $dealer->getCity() : 'cały kraj',
            'model' => $this->getModel()->getName(),
            'version' => $this->getVersion()->getCommercialCode(),
            'dealer_code' => is_null($this->getDealer()) ? null : $this->getDealer()->getCode(),
            'engineType' => $this->getTechnicalData()->getEngineType(),
            'price' => [
                'base' => [
                    'netto' => $price->getBase()->getNetto(),
                    'brutto' => $price->getBase()->getBrutto(),
                ],
                'final' => [
                    'netto' => $price->getFinal()->getNetto(),
                    'brutto' => $price->getFinal()->getBrutto(),
                ],
            ],
            'image' => $images ? $images[0] : null,
            'countOfImage' => count($images),
            'countOfVideos' => 0,
        ];
    }
}
