<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Mtc\Shop\Item as ShopItem;
use App\ProductInfo;


class ParseProductDescriptionsCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'products:parse_descriptions';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Split product descriptions into Info Sections.';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->info('Parsing product descriptions...');

        $items = ShopItem::query()->get();
        foreach ($items as $item) {
            if (! trim($item->full_description)) continue;

            $this->info("- item id:{$item->id}");

            $info_sections = $this->processDescription($item->full_description);

            $is_first = true;
            foreach ($info_sections as $info_section) {
                if ($is_first) {
                    $item->description = $info_section['content'];
                    $item->save();
                    $is_first = false;
                }

                $info_section['item_id'] = $item->id;
                ProductInfo::create($info_section);
            }
        }
    }


    private function processDescription(string $html) : array
    {
        $info_sections = [];
        $title = null;
        $content = '';

        $sort_order = 0;

        $nodes = $this->getFirstLevelNodes($html);
        foreach ($nodes as $node) {
            if ($node->getName() == 'h2') {
                $this->addSection($info_sections, $title, $content, $sort_order);

                $sort_order++;
                $title = (string)$node;
                $content = '';

            } elseif (in_array($node->getName(), [ 'hr', 'br' ])) {
                continue;

            } else {
                $content .= $node->asXML();
            }
        }

        $this->addSection($info_sections, $title, $content, $sort_order);

        return $info_sections;
    }


    private function addSection(array &$sections, ?string $title, ?string $content, int $sort_order)
    {
        if ($title || strlen($content) > 15) {
            $sections[] = [
                'title' => $title ?: 'About',
                'content' => $content,
                'order' => $sort_order,
            ];
        }
    }


    private function getFirstLevelNodes(string $html)
    {
        $doc = new \DOMDocument('1.0', 'UTF-8');
        $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
        $html = preg_replace('/&(?![a-z])/', '&amp;', $html);

        $doc->loadHTML($html);
        $xml = simplexml_import_dom($doc);

        $nodes = $xml->body->xpath("*");

        return $nodes;
    }


    private function getHtml()
    {
        return '<p>Certified & by &amp;IAPMO R&T to NSF/ANSI 372 for  & lead-&ttt;free &nbsp;content&quot;.</p>';
    }
}
