<?php

namespace GriffinForms\Includes\Ai;

use GriffinForms\Includes\Ai\PromptRegistry\StructureSnapshotBuilder;

class LocalTextMutationApplier
{
    protected StructureSnapshotBuilder $snapshot_builder;
    protected PatchPlanApplier $patch_applier;

    public function __construct()
    {
        $this->snapshot_builder = new StructureSnapshotBuilder();
        $this->patch_applier = new PatchPlanApplier();
    }

    public function apply(int $form_id, array $selected_context, string $property, string $value, string $source_prompt = ''): array
    {
        $form_id = absint($form_id);
        $property = sanitize_key($property);
        $value = $property === 'description' ? sanitize_textarea_field($value) : sanitize_text_field($value);

        if ($form_id <= 0 || $property === '' || $value === '') {
            return [
                'success' => false,
                'message' => __('Griffin Assist could not apply that local text update safely.', 'griffinforms-form-builder'),
            ];
        }

        $structure = $this->snapshot_builder->buildFromForm($form_id);
        if (empty($structure['form'])) {
            return [
                'success' => false,
                'message' => __('The target draft could not be loaded for the requested change.', 'griffinforms-form-builder'),
            ];
        }

        $selected_type = $this->normalizeSelectedType($selected_context, $structure);
        if ($selected_type === 'formpage' && in_array($property, ['previous_label', 'next_label'], true)) {
            $value = $this->resolveSafePageNavigationLabel($property, $structure);
        }
        if (!$this->isPropertyAllowed($selected_type, $property)) {
            return [
                'success' => false,
                'message' => __('Griffin Assist could not apply that change to the selected element without risking the rest of the draft.', 'griffinforms-form-builder'),
            ];
        }

        $patch_plan = $this->buildPatchPlan($form_id, $selected_type, $selected_context, $property, $value);
        if (!is_array($patch_plan)) {
            return [
                'success' => false,
                'message' => __('Griffin Assist could not apply that change to the selected element without risking the rest of the draft.', 'griffinforms-form-builder'),
            ];
        }

        return $this->patch_applier->apply($form_id, $patch_plan, $source_prompt);
    }

    protected function normalizeSelectedType(array $selected_context, array $structure): string
    {
        $selected_type = sanitize_key((string) ($selected_context['item_type'] ?? ''));
        if (in_array($selected_type, ['form', 'formpage', 'field'], true)) {
            return $selected_type;
        }

        $selected_id = absint($selected_context['item_id'] ?? 0);
        if ($selected_id <= 0) {
            return 'form';
        }

        foreach ((array) ($structure['pages'] ?? []) as $page) {
            if (absint($page['item_id'] ?? 0) === $selected_id) {
                return 'formpage';
            }

            foreach ((array) ($page['rows'] ?? []) as $row) {
                foreach ((array) ($row['columns'] ?? []) as $column) {
                    foreach ((array) ($column['fields'] ?? []) as $field) {
                        if (absint($field['item_id'] ?? 0) === $selected_id) {
                            return 'field';
                        }
                    }
                }
            }
        }

        return 'form';
    }

    protected function isPropertyAllowed(string $selected_type, string $property): bool
    {
        $allowed = $selected_type === 'form'
            ? ['name', 'heading', 'description', 'submit_label']
            : ($selected_type === 'formpage'
                ? ['heading', 'description', 'previous_label', 'next_label']
                : ['label', 'description', 'placeholder']);

        return in_array($property, $allowed, true);
    }

    protected function buildPatchPlan(int $form_id, string $selected_type, array $selected_context, string $property, string $value): ?array
    {
        if ($selected_type === 'form') {
            return [
                'mode' => 'patch',
                'success_message' => __('Text updated successfully.', 'griffinforms-form-builder'),
                'operations' => [
                    [
                        'op' => 'update_form',
                        'target' => [
                            'scope' => 'form',
                            'item_id' => $form_id,
                        ],
                        'changes' => [
                            $property => $value,
                        ],
                    ],
                ],
            ];
        }

        if ($selected_type === 'formpage') {
            $page_id = absint($selected_context['item_id'] ?? 0);
            if ($page_id <= 0) {
                return null;
            }

            return [
                'mode' => 'patch',
                'success_message' => __('Text updated successfully.', 'griffinforms-form-builder'),
                'operations' => [
                    [
                        'op' => 'update_page',
                        'target' => [
                            'scope' => 'page',
                            'item_id' => $page_id,
                        ],
                        'changes' => [
                            $property => $value,
                        ],
                    ],
                ],
            ];
        }

        if ($selected_type === 'field') {
            $field_id = absint($selected_context['item_id'] ?? 0);
            if ($field_id <= 0) {
                return null;
            }

            return [
                'mode' => 'patch',
                'success_message' => __('Text updated successfully.', 'griffinforms-form-builder'),
                'operations' => [
                    [
                        'op' => 'update_field',
                        'target' => [
                            'scope' => 'field',
                            'item_id' => $field_id,
                        ],
                        'changes' => [
                            $property => $value,
                        ],
                    ],
                ],
            ];
        }

        return null;
    }

    protected function resolveSafePageNavigationLabel(string $property, array $structure): string
    {
        $page_count = count((array) ($structure['pages'] ?? []));
        if ($property === 'next_label') {
            return $page_count <= 1
                ? __('Next', 'griffinforms-form-builder')
                : __('Continue', 'griffinforms-form-builder');
        }

        if ($property === 'previous_label') {
            return $page_count <= 1
                ? __('Previous', 'griffinforms-form-builder')
                : __('Back', 'griffinforms-form-builder');
        }

        return '';
    }
}
