<?php

namespace FluxCms\Core\FieldTypes;

abstract class BaseField
{
    protected string $key;

    protected string $label;

    protected bool $translatable = false;

    protected bool $required = false;

    protected mixed $default = null;

    protected array $rules = [];

    protected array $attributes = [];

    protected ?string $helpText = null;

    protected ?string $placeholder = null;

    public function __construct(string $key, string $label)
    {
        $this->key = $key;
        $this->label = $label;
    }

    public static function make(string $key, string $label): static
    {
        return new static($key, $label);
    }

    /**
     * Configuration Methods
     */
    public function translatable(bool $translatable = true): static
    {
        $this->translatable = $translatable;

        return $this;
    }

    public function required(bool $required = true): static
    {
        $this->required = $required;

        return $this;
    }

    public function default(mixed $default): static
    {
        $this->default = $default;

        return $this;
    }

    public function rules(array|string $rules): static
    {
        $this->rules = is_array($rules) ? $rules : [$rules];

        return $this;
    }

    public function helpText(string $helpText): static
    {
        $this->helpText = $helpText;

        return $this;
    }

    public function placeholder(string $placeholder): static
    {
        $this->placeholder = $placeholder;

        return $this;
    }

    public function attributes(array $attributes): static
    {
        $this->attributes = array_merge($this->attributes, $attributes);

        return $this;
    }

    public function attribute(string $key, mixed $value): static
    {
        $this->attributes[$key] = $value;

        return $this;
    }

    /**
     * Getters
     */
    public function getKey(): string
    {
        return $this->key;
    }

    public function getLabel(): string
    {
        return $this->label;
    }

    public function isTranslatable(): bool
    {
        return $this->translatable;
    }

    public function isRequired(): bool
    {
        return $this->required;
    }

    public function getDefault(): mixed
    {
        return $this->default;
    }

    public function getRules(): array
    {
        $rules = $this->rules;

        if ($this->required) {
            $rules[] = 'required';
        }

        return $rules;
    }

    public function getHelpText(): ?string
    {
        return $this->helpText;
    }

    public function getPlaceholder(): ?string
    {
        return $this->placeholder;
    }

    public function getAttributes(): array
    {
        return $this->attributes;
    }

    public function getAttribute(string $key, mixed $default = null): mixed
    {
        return $this->attributes[$key] ?? $default;
    }

    /**
     * Abstract Methods
     */
    abstract public function getType(): string;

    abstract public function getValidationRules(): array;

    abstract public function toArray(): array;

    /**
     * Value Handling
     */
    public function getValue(array $content, ?string $locale = null): mixed
    {
        if ($this->translatable && $locale) {
            return $content[$this->key][$locale] ?? $this->default;
        }

        return $content[$this->key] ?? $this->default;
    }

    public function setValue(array &$content, mixed $value, ?string $locale = null): void
    {
        if ($this->translatable && $locale) {
            $content[$this->key][$locale] = $value;
        } else {
            $content[$this->key] = $value;
        }
    }

    /**
     * Validation
     */
    public function validate(mixed $value, ?string $locale = null): array
    {
        $rules = $this->getValidationRules();

        if (empty($rules)) {
            return [];
        }

        // Für übersetzbare Felder Locale zu Regeln hinzufügen
        $fieldKey = $this->key;
        if ($locale && $this->translatable) {
            $fieldKey .= '.'.$locale;
        }

        try {
            $validator = validator(
                [$fieldKey => $value],
                [$fieldKey => $rules],
                $this->getValidationMessages(),
                $this->getValidationAttributes()
            );

            return $validator->fails() ? $validator->errors()->get($fieldKey) : [];
        } catch (\Exception $e) {
            return ['Validation error: '.$e->getMessage()];
        }
    }

    /**
     * Validation Messages
     */
    protected function getValidationMessages(): array
    {
        return [
            'required' => 'The :attribute field is required.',
            'string' => 'The :attribute field must be a string.',
            'integer' => 'The :attribute field must be an integer.',
            'numeric' => 'The :attribute field must be a number.',
            'boolean' => 'The :attribute field must be true or false.',
            'array' => 'The :attribute field must be an array.',
            'email' => 'The :attribute field must be a valid email address.',
            'url' => 'The :attribute field must be a valid URL.',
            'max' => 'The :attribute field must not be greater than :max.',
            'min' => 'The :attribute field must be at least :min.',
        ];
    }

    /**
     * Validation Attributes
     */
    protected function getValidationAttributes(): array
    {
        return [
            $this->key => $this->label,
        ];
    }

    /**
     * Rendering
     */
    public function render(array $content = [], ?string $locale = null): string
    {
        $value = $this->getValue($content, $locale);

        $viewData = [
            'field' => $this,
            'value' => $value,
            'locale' => $locale,
            'content' => $content,
            'wireModel' => $this->getWireModel($locale),
            'fieldId' => $this->getFieldId($locale),
            'hasError' => false, // Will be set by parent component
        ];

        $viewName = "flux-cms::fields.{$this->getType()}";

        if (! view()->exists($viewName)) {
            $viewName = 'flux-cms::fields.fallback';
        }

        return view($viewName, $viewData)->render();
    }

    /**
     * Wire Model für Livewire
     */
    public function getWireModel(?string $locale = null): string
    {
        if ($this->translatable && $locale) {
            return "content.{$this->key}.{$locale}";
        }

        return "content.{$this->key}";
    }

    /**
     * Field ID für Labels
     */
    public function getFieldId(?string $locale = null): string
    {
        $id = 'field_'.$this->key;

        if ($this->translatable && $locale) {
            $id .= '_'.$locale;
        }

        return $id;
    }

    /**
     * CSS Classes
     */
    public function getCssClasses(bool $hasError = false): string
    {
        $classes = ['flux-cms-field', 'flux-cms-field--'.$this->getType()];

        if ($this->required) {
            $classes[] = 'flux-cms-field--required';
        }

        if ($hasError) {
            $classes[] = 'flux-cms-field--error';
        }

        if ($this->translatable) {
            $classes[] = 'flux-cms-field--translatable';
        }

        return implode(' ', $classes);
    }

    /**
     * Sanitize Input
     */
    public function sanitizeValue(mixed $value): mixed
    {
        if (is_string($value)) {
            return trim($value);
        }

        return $value;
    }

    /**
     * Transform für Frontend-Ausgabe
     */
    public function transformForDisplay(mixed $value): mixed
    {
        return $value;
    }

    /**
     * Transform für Backend-Bearbeitung
     */
    public function transformForEdit(mixed $value): mixed
    {
        return $value;
    }
}
