<?php

namespace PortalPeople\netsuite\components;

use PortalPeople\netsuite\NetSuiteClient;
use yii\base\Component;
use yii\base\InvalidConfigException;

/**
 * NetSuite Component with OAuth 2.0 JWT Authentication
 * 
 * This component provides easy access to NetSuite API functionality in Yii2 applications
 * 
 * @package PortalPeople\netsuite\components
 */
class NetSuiteComponent extends Component
{
    /**
     * @var string NetSuite account ID
     */
    public $accountId;
    
    /**
     * @var string Client ID from NetSuite integration record
     */
    public $clientId;
    
    /**
     * @var string Client secret from NetSuite integration record
     */
    public $clientSecret;
    
    /**
     * @var string Certificate ID (Key ID) from NetSuite
     */
    public $certificateId;
    
    /**
     * @var string Path to private key file for JWT signing
     */
    public $privateKeyPath;
    
    /**
     * @var string NetSuite user internal ID for impersonation
     */
    public $userId;
    
    /**
     * @var string NetSuite REST API base URL (optional, will be auto-generated if not provided)
     */
    public $baseUrl;
    
    /**
     * @var NetSuiteClient NetSuite client instance
     */
    private $_client;
    
    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
        
        if (empty($this->accountId)) {
            throw new InvalidConfigException('NetSuite account ID must be configured');
        }
        
        if (empty($this->clientId)) {
            throw new InvalidConfigException('NetSuite client ID must be configured');
        }
        
        if (empty($this->clientSecret)) {
            throw new InvalidConfigException('NetSuite client secret must be configured');
        }
        
        if (empty($this->certificateId)) {
            throw new InvalidConfigException('NetSuite certificate ID (Key ID) must be configured');
        }
        
        if (empty($this->privateKeyPath)) {
            throw new InvalidConfigException('Private key path must be configured');
        }
        
        if (empty($this->userId)) {
            throw new InvalidConfigException('NetSuite user ID must be configured');
        }
        
        // Resolve private key path relative to module directory if not absolute
        if (!$this->isAbsolutePath($this->privateKeyPath)) {
            $this->privateKeyPath = \Yii::getAlias('@app') . '/' . ltrim($this->privateKeyPath, '/');
        }
    }
    
    /**
     * Check if path is absolute
     * 
     * @param string $path
     * @return bool
     */
    private function isAbsolutePath($path)
    {
        return (PHP_OS_FAMILY === 'Windows') 
            ? preg_match('/^[a-zA-Z]:[\\\\\/]/', $path)
            : strpos($path, '/') === 0;
    }
    
    /**
     * Get NetSuite client instance
     * 
     * @return NetSuiteClient
     */
    public function getClient()
    {
        if ($this->_client === null) {
            $this->_client = new NetSuiteClient([
                'accountId' => $this->accountId,
                'clientId' => $this->clientId,
                'clientSecret' => $this->clientSecret,
                'certificateId' => $this->certificateId,
                'privateKeyPath' => $this->privateKeyPath,
                'userId' => $this->userId,
                'baseUrl' => $this->baseUrl
            ]);
        }
        
        return $this->_client;
    }
    
    /**
     * Create a new record in NetSuite
     * 
     * @param string $recordType The type of record to create (e.g., 'customer', 'item', 'salesorder')
     * @param array $data Record data
     * @return array Response data
     */
    public function createRecord($recordType, $data)
    {
        return $this->getClient()->post("/record/v1/{$recordType}", $data);
    }
    
    /**
     * Get a record from NetSuite by ID
     * 
     * @param string $recordType The type of record to retrieve
     * @param int $recordId The internal ID of the record
     * @return array Response data
     */
    public function getRecord($recordType, $recordId)
    {
        return $this->getClient()->get("/record/v1/{$recordType}/{$recordId}");
    }
    
    /**
     * Update a record in NetSuite
     * 
     * @param string $recordType The type of record to update
     * @param int $recordId The internal ID of the record
     * @param array $data Updated record data
     * @return array Response data
     */
    public function updateRecord($recordType, $recordId, $data)
    {
        return $this->getClient()->patch("/record/v1/{$recordType}/{$recordId}", $data);
    }
    
    /**
     * Delete a record from NetSuite
     * 
     * @param string $recordType The type of record to delete
     * @param int $recordId The internal ID of the record
     * @return array Response data
     */
    public function deleteRecord($recordType, $recordId)
    {
        return $this->getClient()->delete("/record/v1/{$recordType}/{$recordId}");
    }
    
    /**
     * Search for records in NetSuite
     * 
     * @param string $recordType The type of record to search
     * @param array $criteria Search criteria
     * @param array $options Search options (limit, offset, etc.)
     * @return array Response data
     */
    public function searchRecords($recordType, $criteria = [], $options = [])
    {
        $params = [];
        
        if (!empty($criteria)) {
            $params['q'] = json_encode($criteria);
        }
        
        if (!empty($options['limit'])) {
            $params['limit'] = $options['limit'];
        }
        
        if (!empty($options['offset'])) {
            $params['offset'] = $options['offset'];
        }
        
        return $this->getClient()->get("/query/v1/{$recordType}", $params);
    }
    
    /**
     * Execute a SuiteQL query
     * 
     * @param string $query SuiteQL query string
     * @param array $options Query options (limit, offset, etc.)
     * @return array Response data
     */
    public function executeQuery($query, $options = [])
    {
        $params = ['q' => $query];
        
        if (!empty($options['limit'])) {
            $params['limit'] = $options['limit'];
        }
        
        if (!empty($options['offset'])) {
            $params['offset'] = $options['offset'];
        }
        
        return $this->getClient()->get('/query/v1/suiteql', $params);
    }
    
    /**
     * Get record metadata
     * 
     * @param string $recordType The type of record
     * @return array Response data
     */
    public function getRecordMetadata($recordType)
    {
        return $this->getClient()->get("/record/v1/{$recordType}/metadata");
    }
    
    /**
     * Test the connection to NetSuite
     * 
     * @return bool True if connection is successful
     */
    public function testConnection()
    {
        try {
            $this->getClient()->get('/record/v1/account/1');
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
}