<?php

namespace GriffinForms\Includes\Ai\PromptRegistry;

class JsonExtractor
{
    public function extract(string $content): array
    {
        $content = trim($content);
        if ($content === '') {
            return [null, 'The AI returned an empty response.'];
        }

        $candidate = $this->extractFencedBlock($content);
        if ($candidate === '') {
            $candidate = $this->extractBalancedJson($content);
        }

        if ($candidate === '') {
            return [null, 'The AI did not return a parseable JSON object.'];
        }

        $decoded = json_decode($candidate, true);
        if (!is_array($decoded)) {
            return [null, 'The AI returned JSON that could not be decoded into the expected object shape.'];
        }

        return [$decoded, null];
    }

    protected function extractFencedBlock(string $content): string
    {
        if (!preg_match('/```(?:json)?\s*(.*?)\s*```/si', $content, $matches)) {
            return '';
        }

        $block = trim((string) ($matches[1] ?? ''));
        if ($block === '') {
            return '';
        }

        if (str_starts_with($block, '{') && str_ends_with($block, '}')) {
            return $block;
        }

        return $this->extractBalancedJson($block);
    }

    protected function extractBalancedJson(string $content): string
    {
        $length = strlen($content);
        $start = strpos($content, '{');
        if ($start === false) {
            return '';
        }

        $depth = 0;
        $in_string = false;
        $escaped = false;

        for ($i = $start; $i < $length; $i++) {
            $char = $content[$i];

            if ($escaped) {
                $escaped = false;
                continue;
            }

            if ($char === '\\') {
                $escaped = true;
                continue;
            }

            if ($char === '"') {
                $in_string = !$in_string;
                continue;
            }

            if ($in_string) {
                continue;
            }

            if ($char === '{') {
                $depth++;
            } elseif ($char === '}') {
                $depth--;
                if ($depth === 0) {
                    return substr($content, $start, ($i - $start) + 1);
                }
            }
        }

        return '';
    }
}
