<?php
/**
 * Client Model Class
 *
 * @package Easy_Invoice
 * @subpackage Models
 */

namespace EasyInvoice\Models;

use EasyInvoice\Constants\ClientFields;

/**
 * Client Class
 * 
 * Represents a client entity.
 */
class Client {
    /**
     * The client ID (WP user ID)
     *
     * @var int
     */
    protected $id = 0;
    
    /**
     * Client data array
     *
     * @var array
     */
    protected $data = [];
    
    /**
     * Whether the data is dirty/changed
     *
     * @var bool
     */
    protected $is_dirty = false;
    
    /**
     * Constructor
     *
     * @param int|array $id_or_data The client ID or data array
     */
    public function __construct($id_or_data = 0) {
        if (is_array($id_or_data)) {
            $this->data = $id_or_data;
            $this->id = isset($id_or_data['id']) ? (int) $id_or_data['id'] : 0;
        } else {
            $this->id = (int) $id_or_data;
            // Load data from user meta if we have a valid ID
            if ($this->id > 0) {
                $this->loadFromUserMeta();
            }
        }
    }

    /**
     * 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;
        }
        
        // 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_dirty = 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]);
    }

    /**
     * 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
            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));
    }
    
    /**
     * Load client data from user meta
     */
    protected function loadFromUserMeta() {
        if ($this->id <= 0) {
            return;
        }
        
        // Load all client fields from user meta with simple field names
        $this->data['business_client_name'] = get_user_meta($this->id, ClientFields::BUSINESS_CLIENT_NAME, true);
        $this->data['email'] = get_user_meta($this->id, ClientFields::EMAIL, true);
        $this->data['username'] = get_user_meta($this->id, ClientFields::USERNAME, true);
        $this->data['address'] = get_user_meta($this->id, ClientFields::ADDRESS, true);
        $this->data['extra_info'] = get_user_meta($this->id, ClientFields::EXTRA_INFO, true);
        $this->data['first_name'] = get_user_meta($this->id, ClientFields::FIRST_NAME, true);
        $this->data['last_name'] = get_user_meta($this->id, ClientFields::LAST_NAME, true);
        $this->data['website'] = get_user_meta($this->id, ClientFields::WEBSITE, true);
        $this->data['phone'] = get_user_meta($this->id, ClientFields::PHONE, true); // Now uses dedicated phone key
        
        // If email is not set in meta, try to get it from user data
        if (empty($this->data['email'])) {
            $user = get_user_by('id', $this->id);
            if ($user) {
                $this->data['email'] = $user->user_email;
            }
        }
        
        // If username is not set in meta, try to get it from user data
        if (empty($this->data['username'])) {
            $user = get_user_by('id', $this->id);
            if ($user) {
                $this->data['username'] = $user->user_login;
            }
        }
        
        // If first/last name are not set in meta, try to get them from user data
        if (empty($this->data['first_name']) || empty($this->data['last_name'])) {
            $user = get_user_by('id', $this->id);
            if ($user) {
                if (empty($this->data['first_name'])) {
                    $this->data['first_name'] = $user->first_name;
                }
                if (empty($this->data['last_name'])) {
                    $this->data['last_name'] = $user->last_name;
                }
            }
        }
    }
    
    // Essential methods only
    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->id = $id; }
    public function isDirty(): bool { return $this->is_dirty; }
    public function resetDirty() { $this->is_dirty = false; return $this; }
    public function toArray(): array { return array_merge(['id' => $this->id], $this->data); }
} 