<?php

namespace CouponsPlus\App\Coupon\Tree\Data;

use WP_Post;
use Exception;
use WC_Coupon;
use JsonException;
use CouponsPlus\Original\Environment\Env;
use CouponsPlus\Original\Collections\JSONMapper;
use CouponsPlus\Original\Collections\Collection;

use CouponsPlus\Original\Characters\StringManager;

use const JSON_THROW_ON_ERROR;

class AppDataLoader
{
    private WC_Coupon $coupon;

    public function __construct(WC_Coupon $coupon)
    {
        $this->coupon = $coupon;
    }

    /**
     * @throws JsonException
     */
    public function load() : AppData
    {
        return new AppData(
            $this->getGroveData(),
            $this->getPartialRelations(),
            $this->getPreloadData(),
            $this->getPreconditionsData(),
            $this->getPredates(),
            $this->coupon->get_meta(Env::getWithPrefix('coupon_auto_apply_is_enabled'), true) === 'yes',
            $this->figureOutModel()
        );
        try {
        } catch (Exception $e) {
            return new AppData(
                new DataWithSource('[]', []),
                new DataWithSource('[]', []),
                new DataWithSource('null', null),
                new DataWithSource('null', null),
                false
            );
        }
    }

    /**
     * @throws JsonException
     */
    private function getGroveData() : DataWithSource
    {
        $groveSource = $this->getGroveSource();

        return new DataWithSource(
            $groveSource,
            new Collection(json_decode($groveSource, false, 512, JSON_THROW_ON_ERROR))
        );
    }

    /**
     * @throws JsonException
     */
    private function getPreloadData() : DataWithSource
    {
        $preloadedDataSource = $this->getPreloadedDataSource();

        return new DataWithSource(
            $preloadedDataSource,
            new Collection(json_decode($preloadedDataSource, false, 512, JSON_THROW_ON_ERROR))
        );
    }

    /**
     * @throws JsonException
     */
    private function getPreconditionsData() : DataWithSource
    {
        $preconditionsDataSource = $this->getPreconditionsSource();

        return new DataWithSource(
            $preconditionsDataSource,
            json_decode($preconditionsDataSource, false, 512, JSON_THROW_ON_ERROR)
        );
    }

    /**
     * @throws JsonException
     */
    private function getPredates() : DataWithSource
    {
        $predatesDataSource = $this->getPredatesSource();

        return new DataWithSource(
            $predatesDataSource,
            json_decode($predatesDataSource, false, 512, JSON_THROW_ON_ERROR)
        );
    }
    private function getGroveSource() : string
    {
        return $this->coupon->get_meta(Env::getWithPrefix('grove'), true) ?: '[]';
    }

    private function getPreloadedDataSource() : string
    {
        return $this->coupon->get_meta(Env::getWithPrefix('preloaded_data'), true) ?: '[]';
    }

    private function getPreconditionsSource() : string
    {
        return $this->coupon->get_meta(Env::getWithPrefix('preconditions'), true) ?: 'null';
    }

    private function getPredatesSource() : string
    {
        return $this->coupon->get_meta(Env::getWithPrefix('predates'), true) ?: 'null';
    }

    private function getPartialRelations() : DataWithSource
    {
        $partialRelationsSource = $this->coupon->get_meta(Env::getWithPrefix('testable_partial_relations'), true) ?: '[]';

        return new DataWithSource(
            $partialRelationsSource,
            new Collection(json_decode($partialRelationsSource, false, 512, JSON_THROW_ON_ERROR))
        );
    }

    private function figureOutModel() : string
    {
        $isNew = (new StringManager($this->coupon->get_status()))->contains('draft');
        $modelFromDatabase = $this->coupon->get_meta(Env::getWithPrefix('model'), true);

        if ($isNew) {
            return 'tree'; // all new coupons are trees by default
        }

        // this ain't new, so let's check if it's a legacy coupons+ coupon
        if ($modelFromDatabase) {
            // either tree or legacy saved after migration
            return $modelFromDatabase;
        }

        // no model from database so I figure it's a legacy coupon
        return 'rows';
    }
}