<?php
/**
 * Personality Trait Model for database operations.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// Prevent direct access
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $this->table_name is sanitized in constructor; placeholders are dynamic %s/%d lists bound via prepare().
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class BoostBot_Personality_Trait_Model
 *
 * Handles CRUD operations for personality traits.
 *
 * @since 1.0.0
 */
class BoostBot_Personality_Trait_Model extends BoostBot_Base_Model {

    use BoostBot_Localizable;

    /**
     * Constructor.
     */
    public function __construct() {
        parent::__construct();
        $this->table_name = self::sanitize_identifier( $this->wpdb->prefix . 'boostbot_personality_traits' );
        $this->fillable   = array(
            'name',
            'slug',
            'language',
            'description',
            'prompt_addition',
            'is_active',
        );
        $this->column_types = array(
            'id'        => 'bigint',
            'is_active' => 'tinyint',
        );
    }

    /**
     * Get all active traits.
     *
     * @return array Array of active traits.
     */
    public function get_active() {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return $this->wpdb->get_results(
            "SELECT * FROM {$this->table_name} WHERE is_active = 1 ORDER BY name ASC" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        );
    }

    /**
     * Get trait by slug.
     *
     * @param string $slug The trait slug.
     * @return object|null The trait or null.
     */
    public function get_by_slug( $slug ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return $this->wpdb->get_row(
            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
            $this->wpdb->prepare(
                "SELECT * FROM {$this->table_name} WHERE slug = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                $slug
            )
        );
    }

    /**
     * Get multiple traits by slugs.
     *
     * @param array $slugs Array of trait slugs.
     * @return array Array of traits.
     */
    public function get_by_slugs( $slugs ) {
        if ( empty( $slugs ) || ! is_array( $slugs ) ) {
            return array();
        }

        $placeholders = implode( ',', array_fill( 0, count( $slugs ), '%s' ) );

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return $this->wpdb->get_results(
            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
            $this->wpdb->prepare(
                "SELECT * FROM {$this->table_name} WHERE slug IN ({$placeholders}) AND is_active = 1", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                $slugs
            )
        );
    }

    /**
     * Get prompt additions for multiple traits.
     *
     * @param array $trait_slugs Array of trait slugs.
     * @return string Combined prompt additions.
     */
    public function get_combined_prompt( $trait_slugs ) {
        if ( empty( $trait_slugs ) ) {
            return '';
        }

        $traits = $this->get_by_slugs( $trait_slugs );
        $prompt = '';

        foreach ( $traits as $trait ) {
            if ( ! empty( $trait->prompt_addition ) ) {
                $prompt .= "\n" . $trait->prompt_addition;
            }
        }

        return $prompt;
    }

    /**
     * Validate trait data.
     *
     * @param array    $data The data to validate.
     * @param int|null $id   Optional. The record ID for updates.
     * @return true|WP_Error True if valid, WP_Error otherwise.
     */
    public function validate( $data, $id = null ) {
        $errors = new WP_Error();

        // Name is required
        if ( empty( $data['name'] ) ) {
            $errors->add( 'name_required', __( 'Trait name is required.', 'boostbot' ) );
        }

        // Check slug uniqueness (within same language)
        if ( ! empty( $data['slug'] ) ) {
            $lang     = $data['language'] ?? '';
            $existing = $this->get_by_slug( $data['slug'] );
            if ( $existing && ( ! $id || (int) $existing->id !== (int) $id ) ) {
                if ( '' === $lang || ( isset( $existing->language ) && $existing->language === $lang ) ) {
                    $errors->add( 'slug_exists', __( 'A trait with this slug already exists.', 'boostbot' ) );
                }
            }
        }

        if ( $errors->has_errors() ) {
            return $errors;
        }

        return true;
    }

    /**
     * Sanitize trait data.
     *
     * @param array $data The data to sanitize.
     * @return array The sanitized data.
     */
    public function sanitize( $data ) {
        $sanitized = array();

        if ( isset( $data['name'] ) ) {
            $sanitized['name'] = sanitize_text_field( $data['name'] );
        }

        if ( isset( $data['slug'] ) ) {
            $sanitized['slug'] = sanitize_title( $data['slug'] );
        } elseif ( isset( $data['name'] ) && empty( $data['slug'] ) ) {
            $sanitized['slug'] = sanitize_title( $data['name'] );
        }

        if ( isset( $data['description'] ) ) {
            $sanitized['description'] = sanitize_text_field( $data['description'] );
        }

        if ( isset( $data['prompt_addition'] ) ) {
            $sanitized['prompt_addition'] = sanitize_textarea_field( $data['prompt_addition'] );
        }

        if ( isset( $data['is_active'] ) ) {
            $sanitized['is_active'] = absint( $data['is_active'] ) ? 1 : 0;
        }

        if ( isset( $data['language'] ) ) {
            $sanitized['language'] = sanitize_text_field( $data['language'] );
        }

        return $sanitized;
    }

    /**
     * Restrict a SQL identifier to [A-Za-z0-9_] characters.
     *
     * @param string $identifier Raw identifier.
     * @return string Identifier with disallowed characters removed.
     */
    private static function sanitize_identifier( $identifier ) {
        return preg_replace( '/[^A-Za-z0-9_]/', '', (string) $identifier );
    }
}





