<?php

namespace App\Imports;

use App\Models\Category;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class CategoryImport implements ToCollection, WithHeadingRow
{
    public function collection(Collection $rows)
    {
        // Accept headers: id, name, parent_id from Excel
        $rows = $rows->map(function ($row) {
            return [
                'excel_id'        => (int)($row['id'] ?? 0),
                'name'            => trim($row['name'] ?? ''),
                'parent_excel_id' => isset($row['parent_id']) ? (int)$row['parent_id'] : null,
            ];
        })->filter(fn($row) => $row['name'] !== '');

        // Build node map
        $nodes = [];
        foreach ($rows as $row) {
            $excelId = $row['excel_id'];
            if (!isset($nodes[$excelId])) {
                $nodes[$excelId] = ['data' => $row, 'children' => []];
            } else {
                $nodes[$excelId]['data'] = $row; // fill data if placeholder
            }
        }

        // Link children
        $rootNodes = [];
        foreach ($nodes as $excelId => &$node) {
            $parentExcelId = $node['data']['parent_excel_id'] ?? null;
            if ($parentExcelId && isset($nodes[$parentExcelId])) {
                $nodes[$parentExcelId]['children'][] = &$node;
            } else {
                $rootNodes[] = &$node; // missing/empty parent => root
            }
        }
        unset($node); // break reference

        DB::transaction(function () use ($rootNodes) {
            $this->visited = [];
            foreach ($rootNodes as $rootNode) {
                $this->insertNode($rootNode, null);
            }
        });
    }

    /** @var array<int,bool> */
    private array $visited = [];

    private function insertNode(array $node, ?int $parentId): void
    {
        $excelId = $node['data']['excel_id'] ?? 0;
        if ($excelId && isset($this->visited[$excelId])) {
            // Simple cycle guard; you can throw instead if you prefer strictness
            return;
        }
        if ($excelId) {
            $this->visited[$excelId] = true;
        }

        $category = Category::create([
            'name'        => $node['data']['name'],
            'parent_id'   => $parentId ?? 0,
            'commission'  => 0,
            'order_index' => 0,
            'image'       => '',
        ]);

        foreach ($node['children'] as $childNode) {
            $this->insertNode($childNode, $category->id);
        }
    }
}
