<?php
/**
 * Invoice Item Repository Class
 *
 * @package Easy_Invoice
 * @subpackage Repositories
 */

namespace EasyInvoice\Repositories;

use EasyInvoice\Constants\InvoiceItemFields;
use EasyInvoice\Interfaces\InvoiceItemRepositoryInterface;

/**
 * InvoiceItemRepository Class
 * 
 * Handles data access for invoice items stored as meta fields.
 * Invoice items are stored as '_easy_invoice_items' meta field in the invoice post.
 */
class InvoiceItemRepository implements InvoiceItemRepositoryInterface {
    
    /**
     * The meta key for storing invoice items
     */
    const ITEMS_META_KEY = '_easy_invoice_items';

    /**
     * Get all items for a specific invoice
     *
     * @param int $invoice_id The invoice ID
     * @return array Array of invoice item data
     */
    public function findByInvoice($invoice_id) {
        $items_data = get_post_meta($invoice_id, self::ITEMS_META_KEY, true);
        
        if (empty($items_data) || !is_array($items_data)) {
            return [];
        }
        
        return $items_data;
    }

    /**
     * Get a specific item by index
     *
     * @param int $invoice_id The invoice ID
     * @param int $item_index The item index (0-based)
     * @return array|null The item data or null if not found
     */
    public function find($invoice_id, $item_index = null) {
        $items = $this->findByInvoice($invoice_id);
        
        if ($item_index === null) {
            return $items;
        }
        
        return isset($items[$item_index]) ? $items[$item_index] : null;
    }

    /**
     * Get all items (this method doesn't make sense for meta-based items, but kept for interface compatibility)
     *
     * @param array $args Optional arguments (ignored for meta-based items)
     * @return array Array of invoice item data
     */
    public function all($args = []) {
        // This method doesn't make sense for meta-based items
        // Return empty array as items are tied to specific invoices
        return [];
    }

    /**
     * Add a new item to an invoice
     *
     * @param int $invoice_id The invoice ID
     * @param array $data The item data
     * @return bool True if successful, false otherwise
     */
    public function create($invoice_id, $data) {
        $items = $this->findByInvoice($invoice_id);
        $items[] = $data;
        $result = update_post_meta($invoice_id, self::ITEMS_META_KEY, $items);
        return $result !== false;
    }

    /**
     * Update an existing item
     *
     * @param int $invoice_id The invoice ID
     * @param int $item_index The item index (0-based)
     * @param array $data The item data
     * @return bool True if successful, false otherwise
     */
    public function update($invoice_id, $item_index, $data) {
        $items = $this->findByInvoice($invoice_id);
        if (!isset($items[$item_index])) {
            return false;
        }
        $items[$item_index] = $data;
        $result = update_post_meta($invoice_id, self::ITEMS_META_KEY, $items);
        return $result !== false;
    }

    /**
     * Delete an item
     *
     * @param int $invoice_id The invoice ID
     * @param int $item_index The item index (0-based)
     * @return bool True if successful, false otherwise
     */
    public function delete($invoice_id, $item_index) {
        $items = $this->findByInvoice($invoice_id);
        
        if (!isset($items[$item_index])) {
            return false;
        }
        
        // Remove the item
        unset($items[$item_index]);
        
        // Re-index the array
        $items = array_values($items);
        
        // Update the meta
        $result = update_post_meta($invoice_id, self::ITEMS_META_KEY, $items);
        
        return $result !== false;
    }

    /**
     * Delete all items for an invoice
     *
     * @param int $invoice_id The invoice ID
     * @return bool True if successful, false otherwise
     */
    public function deleteAll($invoice_id) {
        $result = delete_post_meta($invoice_id, self::ITEMS_META_KEY);
        
        return $result !== false;
    }

    /**
     * Count items for an invoice
     *
     * @param int $invoice_id The invoice ID
     * @return int The count of items
     */
    public function count($invoice_id) {
        $items = $this->findByInvoice($invoice_id);
        
        return count($items);
    }

    /**
     * Get total amount for all items in an invoice
     *
     * @param int $invoice_id The invoice ID
     * @return float The total amount
     */
    public function getTotalAmount($invoice_id) {
        $items = $this->findByInvoice($invoice_id);
        $total = 0;
        
        foreach ($items as $item) {
            $quantity = isset($item['quantity']) ? floatval($item['quantity']) : 0;
            $price = isset($item['price']) ? floatval($item['price']) : 0;
            $total += $quantity * $price;
        }
        
        return $total;
    }

    /**
     * Replace all items for an invoice
     *
     * @param int $invoice_id The invoice ID
     * @param array $items Array of item data
     * @return bool True if successful, false otherwise
     */
    public function replaceAll($invoice_id, $items) {
        $result = update_post_meta($invoice_id, self::ITEMS_META_KEY, $items);
        return $result !== false;
    }

    /**
     * Sanitize item data
     *
     * @param array $data The raw item data
     * @return array The sanitized item data
     */
    protected function sanitizeItemData($data) {
        return [
            'name' => isset($data['name']) ? sanitize_text_field($data['name']) : '',
            'description' => isset($data['description']) ? sanitize_textarea_field($data['description']) : '',
            'quantity' => isset($data['quantity']) ? floatval($data['quantity']) : 0,
            'price' => isset($data['price']) ? floatval($data['price']) : 0,
            'tax_rate' => isset($data['tax_rate']) ? floatval($data['tax_rate']) : 0,
            'taxable' => isset($data['taxable']) ? (string) $data['taxable'] : '0',
            'discount' => isset($data['discount']) ? floatval($data['discount']) : 0,
            'discount_type' => isset($data['discount_type']) ? sanitize_text_field($data['discount_type']) : 'percentage',
        ];
    }
} 