<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Base Model Class
 *
 * Abstract class providing common CRUD operations for all models.
 *
 * @package    Kitsune_AI_Platform
 * @subpackage Kitsune_AI_Platform/includes/models
 */
abstract class Kitsune_AI_Platform_Base_Model {

    /**
     * Get the Custom Post Type slug for this model.
     *
     * @return string
     */
    abstract protected function get_post_type();

    /**
     * Get the default meta fields and value for this model.
     * 
     * @return array Key => Default Value
     */
    protected function get_default_meta() {
        return array();
    }

    /**
     * Format a WP_Post object into a model object.
     *
     * @param WP_Post $post
     * @return object
     */
    abstract protected function format_post($post);

    /**
     * Get the meta key prefix.
     *
     * @return string
     */
    protected function get_meta_prefix() {
        return '_ai_platform_';
    }

    /**
     * Get all items with pagination, search, and status filtering.
     *
     * @param array $args Query arguments.
     * @return array Array of formatted objects.
     */
    public function get_all($args = array()) {
        $defaults = array(
            'limit'  => 20,
            'offset' => 0,
            'search' => '',
            'status' => 'all',
        );
        $args = wp_parse_args($args, $defaults);

        $query_args = array(
            'post_type'      => $this->get_post_type(),
            'posts_per_page' => $args['limit'],
            'offset'         => $args['offset'],
            'orderby'        => 'date',
            'order'          => 'DESC',
        );

        // Handle status filter
        if ($args['status'] === 'all') {
            $query_args['post_status'] = array('publish', 'draft', 'private');
        } elseif ($args['status'] === 'active') {
            $query_args['post_status'] = 'publish';
        } elseif ($args['status'] === 'inactive') {
            $query_args['post_status'] = 'draft';
        } else {
            $query_args['post_status'] = $args['status'];
        }

        // Handle search
        if (!empty($args['search'])) {
            $query_args['s'] = sanitize_text_field($args['search']);
        }

        $posts = get_posts($query_args);
        return array_map(array($this, 'format_post'), $posts);
    }

    /**
     * Count all items, optionally filtered by search.
     * Uses wp_count_posts() for empty search for better performance.
     *
     * @param string $search Optional search term.
     * @return int Total count.
     */
    public function count_all($search = '') {
        $search = sanitize_text_field($search);
        $post_type = $this->get_post_type();

        if ($search === '') {
            $counts = wp_count_posts($post_type);
            return (int) ($counts->publish ?? 0) + (int) ($counts->draft ?? 0) + (int) ($counts->private ?? 0);
        }

        $query = new WP_Query(array(
            'post_type' => $post_type,
            'post_status' => array('publish', 'draft', 'private'),
            'posts_per_page' => 1, // Minimize data retrieval
            'fields' => 'ids',     // Only need IDs
            's' => $search,
            'no_found_rows' => false, // We need found_rows
        ));

        return (int) $query->found_posts;
    }

    /**
     * Get a single item by ID.
     *
     * @param int $id Post ID.
     * @return object|null Data object or null if not found.
     */
    public function get($id) {
        $post = get_post($id);
        
        if (!$post || $post->post_type !== $this->get_post_type()) {
            return null;
        }

        return $this->format_post($post);
    }

    /**
     * Get item by ID (alias for get).
     *
     * @param int $id
     * @return object|null
     */
    public function get_by_id($id) {
        return $this->get($id);
    }

    /**
     * Delete an item.
     *
     * @param int $id Post ID.
     * @return bool True on success, false on failure.
     */
    public function delete($id) {
        $post = get_post($id);
        
        if (!$post || $post->post_type !== $this->get_post_type()) {
            return false;
        }

        $result = wp_delete_post($id, true);
        return $result !== false && $result !== null;
    }

    /**
     * Save meta fields for a post.
     *
     * @param int   $post_id Post ID.
     * @param array $data    Data array.
     */
    protected function save_meta($post_id, $data) {
        $default_meta = $this->get_default_meta();
        $prefix = $this->get_meta_prefix();

        foreach ($default_meta as $field => $default) {
            $key = $prefix . $field;
            
            if (isset($data[$field])) {
                update_post_meta($post_id, $key, $data[$field]);
            } elseif (get_post_meta($post_id, $key, true) === '') {
                // Set default only if meta doesn't exist
                update_post_meta($post_id, $key, $default);
            }
        }
    }
}
