<?php

namespace App\Services\Schema;

use Illuminate\Support\Arr;

class SchemaRulesBuilder
{
    public function build(array $schema, array $typeMeta = []): array
    {
        $rules = [];

        $defaultLocale = (string)($typeMeta['default_locale'] ?? 'en');
        $locales = Arr::wrap($typeMeta['locales'] ?? [$defaultLocale]);
        if (!in_array($defaultLocale, $locales, true)) $locales[] = $defaultLocale;

        foreach (($schema['fields'] ?? []) as $field) {
            $key = $field['key'] ?? null;
            if (!$key) continue;

            $type = $field['type'] ?? 'string';
            $required = (bool)($field['required'] ?? false);
            $localized = (bool)($field['localized'] ?? false);

            if ($type === 'repeater') {
                $rules[$key] = [$required ? 'required' : 'nullable', 'array'];
                if (isset($field['minItems'])) $rules[$key][] = 'min:' . (int)$field['minItems'];
                if (isset($field['maxItems'])) $rules[$key][] = 'max:' . (int)$field['maxItems'];

                $rules["{$key}.*"] = ['array'];

                foreach (($field['fields'] ?? []) as $sub) {
                    $subKey = $sub['key'] ?? null;
                    if (!$subKey) continue;

                    if (!empty($sub['localized'])) {
                        $rules["{$key}.*.{$subKey}"] = [($sub['required'] ?? false) ? 'required' : 'nullable', 'array'];

                        foreach ($locales as $loc) {
                            $subRequired = (!empty($sub['required']) && $loc === $defaultLocale) ? 'required' : 'nullable';
                            $rules["{$key}.*.{$subKey}.{$loc}"] = array_merge([$subRequired], $this->scalarTypeRules($sub));
                        }
                    } else {
                        $rules["{$key}.*.{$subKey}"] = array_merge(
                            [($sub['required'] ?? false) ? 'required' : 'nullable'],
                            $this->scalarTypeRules($sub)
                        );
                    }
                }

                continue;
            }

            if ($localized) {
                $rules[$key] = [$required ? 'required' : 'nullable', 'array'];

                foreach ($locales as $loc) {
                    $subRequired = ($required && $loc === $defaultLocale) ? 'required' : 'nullable';
                    $rules["{$key}.{$loc}"] = array_merge([$subRequired], $this->scalarTypeRules($field));
                }

                continue;
            }

            $rules[$key] = array_merge([$required ? 'required' : 'nullable'], $this->scalarTypeRules($field));
        }

        return $rules;
    }

    private function scalarTypeRules(array $field): array
    {
        $type = $field['type'] ?? 'string';
        $r = [];

        switch ($type) {
            case 'string':
                $r[] = 'string';
                if (isset($field['min'])) $r[] = 'min:' . (int)$field['min'];
                if (isset($field['max'])) $r[] = 'max:' . (int)$field['max'];
                if (!empty($field['regex'])) $r[] = 'regex:' . $field['regex'];
                break;

            case 'text':
            case 'richtext':
                $r[] = 'string';
                if (isset($field['max'])) $r[] = 'max:' . (int)$field['max'];
                break;

            case 'number':
                $r[] = 'numeric';
                if (isset($field['min'])) $r[] = 'min:' . (float)$field['min'];
                if (isset($field['max'])) $r[] = 'max:' . (float)$field['max'];
                break;

            case 'boolean':
                $r[] = 'boolean';
                break;

            case 'enum':
                $r[] = 'string';
                $values = Arr::wrap($field['values'] ?? []);
                if (!empty($values)) $r[] = 'in:' . implode(',', $values);
                break;

            case 'date':
                $r[] = 'date';
                break;

            case 'media':
            case 'image':
                // store as URL or array of URLs
                $multiple = (bool)($field['multiple'] ?? false);
                if ($multiple) {
                    $r[] = 'array';
                } else {
                    $r[] = 'string';
                    $r[] = 'url';
                }
                break;

            case 'json':
                $r[] = 'array';
                break;

            default:
                $r[] = 'string';
        }

        return $r;
    }
}
