<?php

namespace GriffinForms\Includes\Fields;

class FieldRegistry
{
    use \GriffinForms\Traits\Singleton;

    protected $definitions;

    protected function setDefinitions()
    {
        $this->definitions = [
            'inputtext' => [
                'field_type' => 'inputtext',
                'label' => 'Single-Line Text',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputText',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputText',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputtext',
            ],
            'inputnumber' => [
                'field_type' => 'inputnumber',
                'label' => 'Number',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputNumber',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputNumber',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputnumber',
            ],
            'inputemail' => [
                'field_type' => 'inputemail',
                'label' => 'Email',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputEmail',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputEmail',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputemail',
            ],
            'inputpassword' => [
                'field_type' => 'inputpassword',
                'label' => 'Password',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputPassword',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputPassword',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputpassword',
            ],
            'inputphone' => [
                'field_type' => 'inputphone',
                'label' => 'Phone Number',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputPhone',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputPhone',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputphone',
            ],
            'inputaddress' => [
                'field_type' => 'inputaddress',
                'label' => 'Address',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputAddress',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputAddress',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputaddress',
            ],
            'inputurl' => [
                'field_type' => 'inputurl',
                'label' => 'URL',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputUrl',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputUrl',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputurl',
            ],
            'inputdate' => [
                'field_type' => 'inputdate',
                'label' => 'Date',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputDate',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputDate',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputdate',
            ],
            'inputtime' => [
                'field_type' => 'inputtime',
                'label' => 'Time',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputTime',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputTime',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputtime',
            ],
            'inputcheckbox' => [
                'field_type' => 'inputcheckbox',
                'label' => 'Checkbox',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputCheckbox',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputCheckBox',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputcheckbox',
            ],
            'inputradio' => [
                'field_type' => 'inputradio',
                'label' => 'Radio',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\InputRadio',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\InputRadio',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Inputradio',
            ],
            'selectfield' => [
                'field_type' => 'selectfield',
                'label' => 'Dropdown',
                'category' => 'common',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\SelectField',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\SelectField',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Selectfield',
            ],
            'textarea' => [
                'field_type' => 'textarea',
                'label' => 'Mult-Line Text',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\TextArea',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\TextArea',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Textarea',
            ],
            'fileupload' => [
                'field_type' => 'fileupload',
                'label' => 'File Upload',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\FileUpload',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\FileUpload',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Fileupload',
            ],
            'termsconditions' => [
                'field_type' => 'termsconditions',
                'label' => 'Terms and Conditions',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\TermsConditions',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\TermsConditions',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Termsconditions',
            ],
            'payment' => [
                'field_type' => 'payment',
                'label' => 'Payment',
                'category' => 'advanced',
                'frontend_class' => '\GriffinForms\Frontend\Html\Forms\Fields\Payment',
                'submission_class' => '\GriffinForms\Admin\Html\Elements\Submission\Payment',
                'validator_class' => '\GriffinForms\Frontend\Security\FieldValidations\Payment',
            ],
        ];

        $this->definitions = apply_filters('griffinforms_register_field_types', $this->definitions);
        $this->definitions = $this->normalizeDefinitions($this->definitions);
    }

    public function getDefinitions(): array
    {
        return $this->definitions;
    }

    public function getFieldTypes(): array
    {
        return array_keys($this->definitions);
    }

    public function getDefinition(string $field_type): array
    {
        $field_type = sanitize_key($field_type);

        return is_array($this->definitions[$field_type] ?? null) ? $this->definitions[$field_type] : [];
    }

    public function getLabel(string $field_type): string
    {
        $definition = $this->getDefinition($field_type);
        $label = trim((string) ($definition['label'] ?? ''));

        return $label !== '' ? $label : '';
    }

    public function getDefinitionsByCategory(string $category): array
    {
        $category = sanitize_key($category);

        return array_filter($this->definitions, static function ($definition) use ($category) {
            return (($definition['category'] ?? 'advanced') === $category);
        });
    }

    public function isRegistered(string $field_type): bool
    {
        return $this->getDefinition($field_type) !== [];
    }

    public function getFrontendClass(string $field_type): string
    {
        return trim((string) ($this->getDefinition($field_type)['frontend_class'] ?? ''));
    }

    public function getSubmissionClass(string $field_type): string
    {
        return trim((string) ($this->getDefinition($field_type)['submission_class'] ?? ''));
    }

    public function getValidatorClass(string $field_type): string
    {
        return trim((string) ($this->getDefinition($field_type)['validator_class'] ?? ''));
    }

    public function getExtension(string $field_type): string
    {
        return trim((string) ($this->getDefinition($field_type)['extension'] ?? ''));
    }

    protected function normalizeDefinitions(array $definitions): array
    {
        $normalized = [];

        foreach ($definitions as $field_type => $definition) {
            if (!is_array($definition)) {
                continue;
            }

            $resolved_field_type = sanitize_key((string) ($definition['field_type'] ?? $field_type));
            if ($resolved_field_type === '') {
                continue;
            }

            $normalized[$resolved_field_type] = [
                'field_type'       => $resolved_field_type,
                'label'            => trim((string) ($definition['label'] ?? '')),
                'category'         => $this->normalizeCategory((string) ($definition['category'] ?? 'advanced')),
                'package_id'       => trim((string) ($definition['package_id'] ?? '')),
                'requires_entitlement' => !empty($definition['requires_entitlement']),
                'frontend_class'   => trim((string) ($definition['frontend_class'] ?? '')),
                'submission_class' => trim((string) ($definition['submission_class'] ?? '')),
                'validator_class'  => trim((string) ($definition['validator_class'] ?? '')),
                'extension'        => sanitize_key((string) ($definition['extension'] ?? '')),
            ];
        }

        return $normalized;
    }

    protected function normalizeCategory(string $category): string
    {
        $category = sanitize_key($category);

        if (!in_array($category, ['common', 'advanced'], true)) {
            return 'advanced';
        }

        return $category;
    }
}
