<?php
/**
 * Localizable trait — opt-in language scoping for models.
 *
 * Models that `use BoostBot_Localizable` gain:
 * - Language-scoped queries  (get_all_for_language, get_default_for_language)
 * - Write-boundary validation (validate_language_on_write)
 *
 * The trait requires the model to have 'language' in its $fillable array
 * and extends BoostBot_Base_Model.
 *
 * @package BoostBot
 * @since   1.3.0
 */

// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

trait BoostBot_Localizable {

    /**
     * Get all records for a specific language.
     *
     * @param string $language Language code (sanitized internally).
     * @param array  $extra    Extra args merged into get_all() (orderby, order, limit, etc.).
     * @return array
     */
    public function get_all_for_language( string $language, array $extra = array() ): array {
        $clean = BoostBot_Language::sanitize( $language );

        $args = array_merge( $extra, array(
            'where' => array_merge( $extra['where'] ?? array(), $clean ? array( 'language' => $clean ) : array() ),
        ) );

        return $this->get_all( $args );
    }

    /**
     * Get the default record for a given language.
     *
     * Fallback chain: requested language → primary language → any default.
     *
     * @param string $language Language code.
     * @return object|null
     */
    public function get_default_for_language( string $language = '' ): ?object {
        $clean = BoostBot_Language::sanitize( $language );

        if ( '' !== $clean ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $result = $this->wpdb->get_row(
                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
                $this->wpdb->prepare(
                    "SELECT * FROM {$this->table_name} WHERE is_default = 1 AND language = %s LIMIT 1", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                    $clean
                )
            );
            if ( $result ) {
                return $result;
            }
        }

        $primary = BoostBot_Language::get_primary();
        if ( '' !== $clean && $primary !== $clean ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $result = $this->wpdb->get_row(
                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
                $this->wpdb->prepare(
                    "SELECT * FROM {$this->table_name} WHERE is_default = 1 AND language = %s LIMIT 1", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                    $primary
                )
            );
            if ( $result ) {
                return $result;
            }
        }

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
    return $this->wpdb->get_row(
        "SELECT * FROM {$this->table_name} WHERE is_default = 1 LIMIT 1" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    );
    }

    /**
     * Validate the language field before a create/update.
     *
     * For admin-managed entities (bots, presets, tones, personalities), validates
     * that the language is in the enabled languages list.
     * For tracking entities (leads, conversations, meetings, widget_usage), skips
     * the enabled-languages check (accepts any valid ISO code).
     *
     * @param array $data   The data being written.
     * @param bool  $strict Whether to enforce enabled-languages check (default: true).
     * @return true|\WP_Error
     */
    public function validate_language_on_write( array $data, bool $strict = true ) {
        if ( ! isset( $data['language'] ) || '' === $data['language'] ) {
            return true;
        }

        $lang = $data['language'];

        if ( ! BoostBot_Language::is_valid( $lang ) ) {
            return new \WP_Error(
                'boostbot_invalid_language',
                sprintf( 'Invalid language code: "%s".', esc_html( $lang ) ),
                array( 'status' => 400 )
            );
        }

        if ( $strict ) {
            return BoostBot_Language::validate_enabled( $lang );
        }

        return true;
    }
}
