<?php
/**
 * Quote Item Model
 *
 * @package     EasyInvoice
 * @author      Your Name
 * @copyright   Copyright (c) 2023, Your Company
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       1.0.0
 */

namespace EasyInvoice\Models;

/**
 * Quote Item Model
 *
 * Represents an item in a quote with dynamic field support.
 *
 * @since 1.0.0
 */
class QuoteItem {
    /**
     * Item ID
     *
     * @var int
     */
    private $id;

    /**
     * Dynamic data storage for all fields
     *
     * @var array
     */
    private $data = [];

    /**
     * Modified flag
     *
     * @var bool
     */
    private $is_modified = false;

    /**
     * Is post flag
     *
     * @var bool
     */
    private $is_post = false;

    /**
     * Magic method to get dynamic properties
     *
     * @since 1.0.0
     * @param string $name Property name
     * @return mixed Property value
     */
    public function __get($name) {
        // Handle special properties
        if ($name === 'id') {
            return $this->id;
        }
        
        // Handle name/title compatibility
        if ($name === 'name' && empty($this->data[$name]) && !empty($this->data['title'])) {
            return $this->data['title'];
        }
        if ($name === 'title' && empty($this->data[$name]) && !empty($this->data['name'])) {
            return $this->data['name'];
        }
        
        // Return from dynamic data array
        return $this->data[$name] ?? null;
    }

    /**
     * Magic method to set dynamic properties
     *
     * @since 1.0.0
     * @param string $name Property name
     * @param mixed $value Property value
     */
    public function __set($name, $value) {
        // Handle special properties
        if ($name === 'id') {
            $this->id = $value;
            return;
        }
        
        // Store in dynamic data array
        $this->data[$name] = $value;
        $this->is_modified = true;
    }

    /**
     * Magic method to check if property exists
     *
     * @since 1.0.0
     * @param string $name Property name
     * @return bool
     */
    public function __isset($name) {
        if ($name === 'id') {
            return isset($this->id);
        }
        
        return isset($this->data[$name]);
    }

    /**
     * Constructor
     *
     * @since 1.0.0
     * @param array $data Item data
     */
    public function __construct($data) {
        $this->data = $data;
        
        if ($data instanceof \WP_Post) {
            $this->is_post = true;
            $this->id = $data->ID;
        } elseif (is_array($data)) {
            $this->is_post = false;
            $this->id = isset($data['id']) ? intval($data['id']) : 0;
        }
    }

    /**
     * Convert to array
     *
     * @since 1.0.0
     * @return array
     */
    public function toArray(): array {
        $data = $this->data;
        $data['id'] = $this->id;

        // Ensure taxable field is properly set as a boolean
        $data['taxable'] = $this->isTaxable();

        // Allow plugins to modify the array data
        return apply_filters('easy_invoice_quote_item_to_array', $data, $this);
    }

    /**
     * Get data for form compatibility
     *
     * @since 1.0.0
     * @return array
     */
    public function getData(): array {
        return $this->toArray();
    }

    /**
     * Check if the model has been modified
     *
     * @since 1.0.0
     * @return bool
     */
    public function isModified(): bool {
        return $this->is_modified;
    }

    /**
     * Determine if the model data has been changed
     *
     * @return bool True if the model data has been changed, false otherwise
     */
    public function isDirty(): bool {
        return $this->is_modified;
    }

    /**
     * Reset the dirty flag
     *
     * @return $this For method chaining
     */
    public function resetDirty() {
        $this->is_modified = false;
        return $this;
    }

    /**
     * Get the calculated amount for this item
     *
     * @since 1.0.0
     * @return float The calculated amount
     */
    public function getAmount(): float {
        $quantity = floatval($this->data['quantity'] ?? 0);
        $price = floatval($this->data['price'] ?? 0);
        
        // Calculate base total
        $base_total = $quantity * $price;
        
        // Only apply adjustment percentage if the adjust field setting is enabled
        if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()) {
            $adjust_percentage = floatval($this->data['adjust_percentage'] ?? 0);
            if ($adjust_percentage != 0) {
                $base_total = $base_total * (1 + $adjust_percentage / 100);
            }
        }
        
        return $base_total;
    }

    /**
     * Check if the item is taxable
     *
     * @since 1.0.0
     * @return bool
     */
    public function isTaxable(): bool {
        // Convert various values to boolean
        $value = $this->data['taxable'] ?? true;
        if (is_string($value)) {
            $value = strtolower($value);
            return $value === '1' || $value === 'true' || $value === 'yes' || $value === 'on';
        }
        return (bool) $value;
    }

    /**
     * Dynamic getter method
     *
     * @since 1.0.0
     * @param string $name Method name
     * @param array $arguments Method arguments
     * @return mixed
     */
    public function __call($name, $arguments) {
        // Handle getter methods (getFieldName)
        if (strpos($name, 'get') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'get' prefix
            
            // Special handling for getName() to check both 'name' and 'title' fields
            if ($field_name === 'name') {
                if (!empty($this->data['name'])) {
                    return $this->data['name'];
                } elseif (!empty($this->data['title'])) {
                    return $this->data['title'];
                }
                return null;
            }
            
            return $this->__get($field_name);
        }
        
        // Handle setter methods (setFieldName)
        if (strpos($name, 'set') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'set' prefix
            $value = $arguments[0] ?? null;
            $this->__set($field_name, $value);
            return null;
        }
        
        // Handle isset methods (isFieldName)
        if (strpos($name, 'is') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 2)); // Remove 'is' prefix
            return (bool) $this->__get($field_name);
        }
        
        // Handle has methods (hasFieldName)
        if (strpos($name, 'has') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'has' prefix
            return !empty($this->__get($field_name));
        }
        
        throw new \BadMethodCallException("Method $name does not exist");
    }

    /**
     * Convert camelCase to snake_case
     *
     * @since 1.0.0
     * @param string $camelCase
     * @return string
     */
    private function camelCaseToSnakeCase($camelCase) {
        return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $camelCase));
    }
} 