<?php

namespace Fotogenic_AI;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Single source of truth for selection keys, required vs optional, and defaults.
 * Used by UI validation, server validation/default filling, and auto-config mapping.
 * No target-specific allowlists.
 */
final class Selection_Schema {

    /** @var string[] All valid selection keys (required + optional). */
    private const SELECTION_KEYS = [
        'emotion',
        'styling',
        'clothing',
        'action',
        'expression',
        'grip',
        'framing',
        'setting',
        'focus',
        'bgElements',
        'lighting',
        'atmosphere',
        'angle',
        'shotSize',
        'aspectRatio',
    ];

    /** @var string[] Keys required by the API (must be present in payload or filled from defaults). */
    private const REQUIRED_KEYS = [
        'emotion',
        'styling',
        'clothing',
        'action',
        'expression',
        'grip',
        'framing',
        'setting',
        'focus',
        'bgElements',
        'lighting',
        'atmosphere',
        'angle',
        'shotSize',
    ];

    /** @var array<string,string> Default selection id per key when not provided. */
    private const DEFAULTS = [];

    /**
     * All valid selection keys.
     *
     * @return string[]
     */
    public static function get_selection_keys(): array {
        return self::SELECTION_KEYS;
    }

    /**
     * Keys required by the API (must be present or filled from schema defaults).
     *
     * @return string[]
     */
    public static function get_required_keys(): array {
        return self::REQUIRED_KEYS;
    }

    /**
     * Default value for a key when API requires it and request did not send it.
     * Returns null if no schema default (caller may use config default or leave empty).
     *
     * @param string $key Selection key.
     * @return string|null Default id or null.
     */
    public static function get_default_for_key( string $key ): ?string {
        return self::DEFAULTS[ $key ] ?? null;
    }

    /**
     * All schema defaults (for filling missing required keys).
     *
     * @return array<string,string>
     */
    public static function get_defaults(): array {
        return self::DEFAULTS;
    }

    /**
     * Whether the key is valid per schema.
     *
     * @param string $key Selection key.
     * @return bool
     */
    public static function is_valid_key( string $key ): bool {
        return in_array( $key, self::SELECTION_KEYS, true );
    }

    /**
     * Fill missing required keys in selections from schema defaults.
     * Only adds keys that are required and have a schema default and are not already set.
     *
     * @param array<string,array{id?:string}> $selections Current selections (key => [ 'id' => ... ]).
     * @return array<string,array{id:string}> Merged selections (only adds from schema defaults).
     */
    public static function fill_required_from_defaults( array $selections ): array {
        $out = $selections;
        foreach ( self::REQUIRED_KEYS as $key ) {
            if ( isset( $out[ $key ] ) && is_array( $out[ $key ] ) && ! empty( (string) ( $out[ $key ]['id'] ?? '' ) ) ) {
                continue;
            }
            $default_id = self::get_default_for_key( $key );
            if ( null !== $default_id ) {
                $out[ $key ] = [ 'id' => $default_id ];
            }
        }
        return $out;
    }
}
