<?php

declare(strict_types=1);

namespace App\Framework\View\Table\Generators;

use App\Framework\View\Table\CellFormatter;
use App\Framework\View\Table\Table;
use App\Framework\View\Table\TableColumn;
use App\Framework\View\Table\TableGenerator;
use App\Framework\View\Table\TableOptions;
use App\Framework\View\Table\TableRow;

final readonly class RouteTableGenerator implements TableGenerator
{
    public function generate(object|array $data, ?TableOptions $options = null): Table
    {
        if (! is_array($data)) {
            throw new \InvalidArgumentException('RouteTableGenerator expects array data');
        }

        $columns = [
            new TableColumn(
                key: 'method',
                header: 'Method',
                cssClass: 'route-method',
                formatter: $this->createMethodFormatter()
            ),
            TableColumn::text('path', 'Path', 'route-path'),
            new TableColumn(
                key: 'name',
                header: 'Name',
                cssClass: 'route-name',
                formatter: $this->createNameFormatter()
            ),
            TableColumn::text('controller', 'Controller', 'route-controller'),
            TableColumn::text('handler', 'Handler', 'route-handler'),
            new TableColumn(
                key: 'is_protected',
                header: 'Auth',
                cssClass: 'route-auth',
                formatter: $this->createAuthFormatter()
            ),
        ];

        $rows = [];
        foreach ($data as $route) {
            $rows[] = TableRow::fromData($route, $columns, 'route-row');
        }

        $tableOptions = $options ?? new TableOptions(
            striped: true,
            bordered: true,
            hover: true,
            responsive: true,
            emptyMessage: 'No routes found'
        );

        return new Table(
            columns: $columns,
            rows: $rows,
            cssClass: 'admin-table route-table',
            options: $tableOptions,
            id: 'routesTable'
        );
    }

    public function supports(object|array $data): bool
    {
        if (! is_array($data) || empty($data)) {
            return false;
        }

        $firstItem = reset($data);
        if (! is_array($firstItem)) {
            return false;
        }

        // Check if it has route structure
        return isset($firstItem['path']) && isset($firstItem['method']);
    }

    private function createMethodFormatter(): CellFormatter
    {
        return new class () implements CellFormatter {
            public function format(mixed $value): string
            {
                if ($value === null || $value === '') {
                    return '';
                }

                $method = strtoupper((string) $value);
                $colorClass = match ($method) {
                    'GET' => 'success',
                    'POST' => 'primary',
                    'PUT', 'PATCH' => 'warning',
                    'DELETE' => 'error',
                    default => 'secondary'
                };

                return sprintf(
                    '<span class="method-badge method-badge--%s">%s</span>',
                    $colorClass,
                    htmlspecialchars($method, ENT_QUOTES)
                );
            }
        };
    }

    private function createNameFormatter(): CellFormatter
    {
        return new class () implements CellFormatter {
            public function format(mixed $value): string
            {
                if ($value === null || $value === '') {
                    return '<em class="text-muted">unnamed</em>';
                }

                // Handle backed enums by accessing their value property
                if ($value instanceof \BackedEnum) {
                    return '<code>' . htmlspecialchars((string) $value->value, ENT_QUOTES) . '</code>';
                }

                return '<code>' . htmlspecialchars((string) $value, ENT_QUOTES) . '</code>';
            }
        };
    }

    private function createAuthFormatter(): CellFormatter
    {
        return new class () implements CellFormatter {
            public function format(mixed $value): string
            {
                $isProtected = (bool) $value;

                if ($isProtected) {
                    return '<span class="auth-badge auth-badge--protected" title="Protected">🔒</span>';
                } else {
                    return '<span class="auth-badge auth-badge--public" title="Public">🌐</span>';
                }
            }
        };
    }
}
