<?php

namespace AIPT\Api\AutomationJobs\Models;

/**
 * AutomationJob Model
 * 
 * Represents an automation job with validation and data management
 * Following Single Responsibility Principle
 * 
 * @since 2.3.0
 */
class AutomationJob {
    
    /**
     * Job ID
     * @var int
     */
    public $id;
    
    /**
     * Job name
     * @var string
     */
    public $name;
    
    /**
     * Job description
     * @var string
     */
    public $description;
    
    /**
     * Tool type (advanced, standard, title)
     * @var string
     */
    public $tool_type;
    
    /**
     * Job status (pending, running, paused, completed, failed)
     * @var string
     */
    public $status;
    
    /**
     * Progress percentage (0-100)
     * @var int
     */
    public $progress;
    
    /**
     * Total products to process
     * @var int
     */
    public $total_products;
    
    /**
     * Number of processed products
     * @var int
     */
    public $processed_products;
    
    /**
     * Number of failed products
     * @var int
     */
    public $failed_products;
    
    /**
     * Job settings (JSON)
     * @var array
     */
    public $settings;
    
    /**
     * Schedule configuration (JSON)
     * @var array
     */
    public $schedule_config;
    
    /**
     * Product filter configuration (JSON)
     * @var array
     */
    public $product_filter;
    
    /**
     * Next run datetime
     * @var string
     */
    public $next_run;
    
    /**
     * Job started datetime
     * @var string
     */
    public $started_at;
    
    /**
     * Job completed datetime
     * @var string
     */
    public $completed_at;
    
    /**
     * Error message
     * @var string
     */
    public $error_message;
    
    /**
     * User ID who created the job
     * @var int
     */
    public $created_by;
    
    /**
     * Created datetime
     * @var string
     */
    public $created_at;
    
    /**
     * Updated datetime
     * @var string
     */
    public $updated_at;
    
    /**
     * Valid tool types
     */
    const VALID_TOOL_TYPES = ['advanced', 'standard', 'title'];
    
    /**
     * Valid statuses (no backward-compat needed): preparing → ready → running/paused → completed/failed
     */
    const VALID_STATUSES = ['preparing', 'ready', 'running', 'paused', 'completed', 'failed'];

    /**
     * Valid status transitions: from_status => [allowed_to_statuses]
     */
    const VALID_TRANSITIONS = [
        'preparing' => ['ready', 'failed'],
        'ready'     => ['running', 'failed'],
        'running'   => ['paused', 'completed', 'failed'],
        'paused'    => ['running', 'failed'],
        'completed' => [],
        'failed'    => ['ready'],
    ];
    
    /**
     * Constructor
     * 
     * @param array $data Job data
     */
    public function __construct($data = []) {
        if (!empty($data)) {
            $this->populate($data);
        }
    }
    
    /**
     * Populate object with data
     *
     * @param array $data Job data
     */
    public function populate($data) {
        $this->id = isset($data['id']) ? (int) $data['id'] : null;
        $this->name = isset($data['name']) ? sanitize_text_field($data['name']) : '';
        $this->description = isset($data['description']) ? sanitize_textarea_field($data['description']) : '';

        $this->tool_type = isset($data['tool_type']) ? sanitize_text_field($data['tool_type']) :
                          (isset($data['toolType']) ? sanitize_text_field($data['toolType']) : '');

        $this->status = isset($data['status']) ? sanitize_text_field($data['status']) : 'preparing';
        $this->progress = isset($data['progress']) ? (int) $data['progress'] : 0;
        $this->total_products = isset($data['total_products']) ? (int) $data['total_products'] :
                               (isset($data['totalProducts']) ? (int) $data['totalProducts'] : 0);
        $this->processed_products = isset($data['processed_products']) ? (int) $data['processed_products'] :
                                   (isset($data['processedProducts']) ? (int) $data['processedProducts'] : 0);
        $this->failed_products = isset($data['failed_products']) ? (int) $data['failed_products'] : 0;

        $this->settings = isset($data['settings']) ? $this->parseJsonField($data['settings']) : [];

        $schedule_data = isset($data['schedule_config']) ? $data['schedule_config'] :
                        (isset($data['schedule']) ? $data['schedule'] : []);
        $this->schedule_config = $this->parseJsonField($schedule_data);

        $filter_data = isset($data['product_filter']) ? $data['product_filter'] :
                      (isset($data['productFilter']) ? $data['productFilter'] : null);
        $this->product_filter = $filter_data ? $this->parseJsonField($filter_data) : null;

        $this->next_run = isset($data['next_run']) ? $data['next_run'] : null;
        $this->started_at = isset($data['started_at']) ? $data['started_at'] : null;
        $this->completed_at = isset($data['completed_at']) ? $data['completed_at'] : null;
        $this->error_message = isset($data['error_message']) ? $data['error_message'] : null;
        $this->created_by = isset($data['created_by']) ? (int) $data['created_by'] : get_current_user_id();
        $this->created_at = isset($data['created_at']) ? $data['created_at'] : current_time('mysql');
        $this->updated_at = isset($data['updated_at']) ? $data['updated_at'] : null;
    }
    
    /**
     * Parse JSON field
     * 
     * @param mixed $value Field value
     * @return array|null
     */
    private function parseJsonField($value) {
        if (is_string($value)) {
            $decoded = json_decode($value, true);
            return json_last_error() === JSON_ERROR_NONE ? $decoded : [];
        }
        return is_array($value) ? $value : [];
    }
    
    /**
     * Validate job data
     * 
     * @return array Validation errors
     */
    public function validate() {
        $errors = [];
        

        if (empty($this->name)) {
            $errors['name'] = 'Job name is required';
        }
        
        if (empty($this->tool_type)) {
            $errors['tool_type'] = 'Tool type is required';
        } elseif (!in_array($this->tool_type, self::VALID_TOOL_TYPES)) {
            $errors['tool_type'] = 'Invalid tool type. Must be one of: ' . implode(', ', self::VALID_TOOL_TYPES);
        }
        
        if (!in_array($this->status, self::VALID_STATUSES)) {
            $errors['status'] = 'Invalid status. Must be one of: ' . implode(', ', self::VALID_STATUSES);
        }
        

        if ($this->progress < 0 || $this->progress > 100) {
            $errors['progress'] = 'Progress must be between 0 and 100';
        }
        

        if (empty($this->settings)) {
            $errors['settings'] = 'Job settings are required';
        } else {
            $settings_errors = $this->validateSettings();
            if (!empty($settings_errors)) {
                $errors['settings'] = $settings_errors;
            }
        }
        

        if (empty($this->schedule_config)) {
            $errors['schedule_config'] = 'Schedule configuration is required';
        } else {
            $schedule_errors = $this->validateSchedule();
            if (!empty($schedule_errors)) {
                $errors['schedule_config'] = $schedule_errors;
            }
        }
        
        return $errors;
    }
    
    /**
     * Validate settings
     * 
     * @return array Validation errors
     */
    private function validateSettings() {
        $errors = [];
        

        $required_fields = ['provider', 'model'];
        foreach ($required_fields as $field) {
            if (empty($this->settings[$field])) {
                $errors[$field] = ucfirst($field) . ' is required';
            }
        }
        

        if (!empty($this->settings['provider'])) {
            $valid_providers = ['openai', 'gemini', 'openrouter', 'claude'];
            if (!in_array($this->settings['provider'], $valid_providers)) {
                $errors['provider'] = 'Invalid provider. Must be one of: ' . implode(', ', $valid_providers);
            }
        }
        
        return $errors;
    }
    
    /**
     * Validate schedule configuration
     * 
     * @return array Validation errors
     */
    private function validateSchedule() {
        $errors = [];
        
        if (empty($this->schedule_config['type'])) {
            $errors['type'] = 'Schedule type is required';
        } else {
            $valid_types = ['once', 'daily', 'weekly', 'monthly'];
            if (!in_array($this->schedule_config['type'], $valid_types)) {
                $errors['type'] = 'Invalid schedule type. Must be one of: ' . implode(', ', $valid_types);
            }
        }
        
        return $errors;
    }
    
    /**
     * Convert to array for database storage
     * 
     * @return array
     */
    public function toArray() {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'tool_type' => $this->tool_type,
            'status' => $this->status,
            'progress' => $this->progress,
            'total_products' => $this->total_products,
            'processed_products' => $this->processed_products,
            'failed_products' => $this->failed_products,
            'settings' => wp_json_encode($this->settings),
            'schedule_config' => wp_json_encode($this->schedule_config),
            'product_filter' => $this->product_filter ? wp_json_encode($this->product_filter) : null,
            'next_run' => $this->next_run,
            'started_at' => $this->started_at,
            'completed_at' => $this->completed_at,
            'error_message' => $this->error_message,
            'created_by' => $this->created_by,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at
        ];
    }
    
    /**
     * Check if transition to given status is valid per state machine rules
     * 
     * @param string $to_status Target status
     * @return bool
     */
    public function canTransitionTo($to_status) {
        if (!isset(self::VALID_TRANSITIONS[$this->status])) {
            return false;
        }
        return in_array($to_status, self::VALID_TRANSITIONS[$this->status], true);
    }

    /**
     * Check if job can be paused
     * 
     * @return bool
     */
    public function canBePaused() {
        return $this->canTransitionTo('paused');
    }
    
    /**
     * Check if job can be resumed
     * 
     * @return bool
     */
    public function canBeResumed() {
        return $this->canTransitionTo('running');
    }
    
    /**
     * Check if job is active (running or paused)
     * 
     * @return bool
     */
    public function isActive() {
        return in_array($this->status, ['running', 'paused']);
    }
    
    /**
     * Check if job is completed
     * 
     * @return bool
     */
    public function isCompleted() {
        return in_array($this->status, ['completed', 'failed']);
    }
}
