<?php 
namespace PortalPeople\netsuite;
use Yii;
use yii\base\Module as BaseModule;
use yii\helpers\Html;
use yii\base\Event;
use yii\base\View;
/**
 * Netsuite Sync Module
 * 
 * This module provides integration with Netsuite API for product and Order synchronization
 */
class Module extends BaseModule implements \yii\base\BootstrapInterface
{
    public $controllerNamespace = 'PortalPeople\netsuite\controllers';
    
    public function bootstrap($app)
    {
         $this->id = 'netsuite';
         Yii::setAlias('@config', $_SERVER['DOCUMENT_ROOT'] . '/config');
        // Register the module if not already registered
        //   Yii::warning($app->getModules()[$this->id], 'Module bootstrap');
        if (!isset($app->getModules()[$this->id])) {
            $app->setModule($this->id, $this);
        }
        
        // Register URL rules
        $app->urlManager->addRules([
            // Specific action routes (most specific first)
            "{$this->id}/<action:['settings']+>" => "{$this->id}/config/<action>",
            "{$this->id}/<action:[\w\-]+>" => "{$this->id}/netsuite/<action>",
            "{$this->id}/<controller:[\w\-]+>/<action:[\w\-]+>" => "{$this->id}/<controller>/<action>",
            
        ], false); // false = append rules (don't prepend)

        // Register API-specific routes when running in the API application
        if (!($app instanceof \yii\console\Application) && stripos($app->id, 'api') !== false) {
            // Provide both explicit and permissive aliases for API endpoints.
            // Some clients call `/api/netsuite/orderupdate` or `/api/netsuite/orderUpdate`.
            $app->urlManager->addRules([
                // canonical lowercase actions
                "{$this->id}/updateorder" => "{$this->id}/api/netsuite/updateorder",
                "{$this->id}/pickorder" => "{$this->id}/api/netsuite/pickorder",
                // common historic aliases (preserve backward compatibility)
                "{$this->id}/orderupdate" => "{$this->id}/api/netsuite/updateorder",
                "{$this->id}/orderUpdate" => "{$this->id}/api/netsuite/updateorder",
                "{$this->id}/order_update" => "{$this->id}/api/netsuite/updateorder",
            ], false);
        }
        
        // Load NetSuite configuration and merge into Yii::$app->params
        $this->loadNetSuiteConfig();
        
        // Register NetSuite client component
        $this->registerNetSuiteClient($app);
        
        $this->setEvents();

        // Register all view customizations from this module's config directory
        //AdminViewsRegistry::registerModuleViews('netsuite');
    }
    
    /**
     * Load NetSuite configuration from ns.php and merge into application params
     */
    protected function loadNetSuiteConfig()
    {
        $configFile = Yii::getAlias('@config/netsuite/ns.php');
        
        if (file_exists($configFile)) {
            try {
                $netsuiteConfig = require $configFile;
                
                if (is_array($netsuiteConfig)) {
                    // Decrypt sensitive fields if in live state
                    $netsuiteConfig = $this->decryptConfigData($netsuiteConfig);
                    
                    // Merge into application params
                    Yii::$app->params['netsuite'] = array_merge(
                        Yii::$app->params['netsuite'] ?? [],
                        $netsuiteConfig
                    );
                    
                    if (YII_DEBUG) {
                        Yii::info('NetSuite configuration loaded from ns.php', __CLASS__);
                    }
                }
            } catch (\Exception $e) {
                Yii::error("Failed to load NetSuite config: " . $e->getMessage(), __CLASS__);
            }
        } else {
            // Initialize with default empty config
            if (!isset(Yii::$app->params['netsuite'])) {
                Yii::$app->params['netsuite'] =(new \PortalPeople\netsuite\models\SettingsForm())->attributes;
            }
        }
    }

    /**
     * Decrypt encrypted configuration data if app state is 'live'
     * 
     * @param array $config Configuration array
     * @return array Decrypted configuration
     */
    protected function decryptConfigData($config)
    {
        // Check if app is in live state - adjust based on your app's state detection
        $isLive = (Yii::$app->state ?? null) === 'live' || 
                  (defined('YII_ENV') && YII_ENV === 'prod');
        
        if (!$isLive) {
            return $config;
        }
        
        // Sensitive fields that may be encrypted
        $sensitiveFields = ['consumer_key', 'consumer_secret', 'token_id', 'token_secret', 'certificate_id', 'decryption_key'];
        
        foreach ($sensitiveFields as $field) {
            if (isset($config[$field]) && is_string($config[$field])) {
                $value = $config[$field];
                
                // Check if value is encrypted (prefixed with 'encrypted::')
                if (strpos($value, 'encrypted::') === 0) {
                    try {
                        $encryptedData = substr($value, 11); // Remove 'encrypted::' prefix
                        $decrypted = Yii::$app->security->decryptByPassword($encryptedData, '');
                        $config[$field] = $decrypted;
                    } catch (\Exception $e) {
                        Yii::error("Failed to decrypt NetSuite config field '{$field}': " . $e->getMessage(), __CLASS__);
                    }
                }
            }
        }
        
        return $config;
    }

    /**
     * Register NetSuiteClient as an application component
     */
    protected function registerNetSuiteClient($app)
    {
        try {
            $netsuiteConfig = Yii::$app->params['netsuite'] ?? [];
            
            // Only register if we have the required configuration
            // Check for OAuth2 JWT config (preferred)
            $hasOAuth2 = !empty($netsuiteConfig['account_id']) && !empty($netsuiteConfig['certificate_id']) && 
                         !empty($netsuiteConfig['private_key_path']);
            
            // Also accept consumer_key/consumer_secret (legacy)
            $hasLegacy = !empty($netsuiteConfig['account_id']) && !empty($netsuiteConfig['consumer_key']) && 
                         !empty($netsuiteConfig['consumer_secret']);
            
            if ($hasOAuth2 || $hasLegacy) {
                $componentConfig = [
                    'class' => 'PortalPeople\netsuite\NetSuiteClient',
                    'accountId' => $netsuiteConfig['account_id'],
                ];
                
                // Use OAuth2 JWT if available
                if ($hasOAuth2) {
                    $componentConfig['clientId'] = $netsuiteConfig['client_id'] ?? $netsuiteConfig['consumer_key'] ?? '';
                    $componentConfig['clientSecret'] = $netsuiteConfig['client_secret'] ?? $netsuiteConfig['consumer_secret'] ?? '';
                    $componentConfig['certificateId'] = $netsuiteConfig['certificate_id'];
                    $componentConfig['privateKeyPath'] = $netsuiteConfig['private_key_path'];
                    $componentConfig['userId'] = $netsuiteConfig['user_id'] ?? '';
                } else {
                    // Fall back to consumer key/secret if provided
                    $componentConfig['clientId'] = $netsuiteConfig['consumer_key'];
                    $componentConfig['clientSecret'] = $netsuiteConfig['consumer_secret'];
                    $componentConfig['certificateId'] = $netsuiteConfig['certificate_id'] ?? '';
                    $componentConfig['privateKeyPath'] = $netsuiteConfig['private_key_path'] ?? '';
                    $componentConfig['userId'] = $netsuiteConfig['user_id'] ?? '';
                }
                
                if (!empty($netsuiteConfig['base_url'])) {
                    $componentConfig['baseUrl'] = $netsuiteConfig['base_url'];
                }
                
                // Register the component
                Yii::$app->set('netsuiteClient', $componentConfig);
                
                if (YII_DEBUG) {
                    Yii::info('NetSuite client registered as application component', __CLASS__);
                }
            } else {
                if (YII_DEBUG) {
                    Yii::warning('NetSuite configuration incomplete. NetSuite client not registered.', __CLASS__);
                }
            }
        } catch (\Exception $e) {
            Yii::error("Failed to register NetSuite client: " . $e->getMessage(), __CLASS__);
        }
    }


    public function setEvents(){
        Event::on(\modules\custom\models\ProductsData::class, 'products-set-data-types', function($event){
            $event->buttons['netsuite'] = 'netsuite';
        });
        Yii::$app->on('products-after-DataLoad-netsuite', function($event){
            $event->result = \PortalPeople\netsuite\models\products\Netsuite::class;
            }
        );
        \yii\base\Event::on(
            View::class, 
            'products_index_columns', 
            function($event){
                Yii::warning('Adding NetSuite columns to products index', 'netsuite');
                $model = $event->model;
                $event->customData['netsuite_id'] = [
                    'order' => 6,
                    'label' => 'NetSuite ID',
                    'value' => function($model) {
                        return $model->data->netsuite->erpid ?? null;
                    },
                ];
                $event->customData['netsuite_unit'] = [
                    'order' => 7,
                    'label' => 'NetSuite Unit',
                    'value' => function($model) {
                        return $model->data->netsuite->unit ?? null;
                    },
                ];
                $event->customData['magento_name'] = [
                    'order' => 7,
                    'label' => 'Magento Name',
                    'value' => function($model) {
                        return $model->data->magento->name ?? null;
                    },
                ];
                return $event;
        });
        Event::on(\backend\models\CartsData::class, 'carts-set-data-types', function($event){
            $event->customData['netsuite'] = 'netsuite';
        });
        Yii::$app->on(
            'carts-after-DataLoad-netsuite', 
            function($event){
                $event->result = \PortalPeople\netsuite\models\carts\Netsuite::class;
            }
        );
        Event::on(
            View::class,
            'cart-view-cartsbeview-before', 
            function($event){
                echo Yii::$app->view->render('@PortalPeople/netsuite/views/cart/js', ['model' => $event->model]);
            }
        );

        Event::on(
            View::class,
            'cart-view-tabs-after', 
            function($event){
                $event->buttons[] = [
                    'label' => 'NetSuite Integration',
                    'content' => Yii::$app->view->render('@PortalPeople/netsuite/views/cart/viewtabs/_netsuite_integration_tab', ['model' => $event->model]),
                ];
            }
        );
        Event::on(
            View::class,
            'cart-order-after', 
            function($event){
                \Yii::$app->netsuitequeue
                    ->jobname('Send to ERP (NetSuite)')    
                    ->relatedid($this->id)    
                    ->delay(120)
                    ->ttr(300)
                    ->push(new \portalpeople\netsuite\jobs\Sendtonetsuite(['id' => $this->id]));
            }
        );
        Event::on(
            View::class,
            'cart-view-header-after', 
            function($event){
                $AccountID = Yii::$app->params['netsuite']['account_id'];
                $ns = empty($event->model->netsuiteid) == false ? json_decode($event->model->netsuiteid, 1) : false;
                if($ns === false){
                    return;
                }
                foreach($ns as $key => $value){
                    $event->buttons[] = [
                        'label' => 'NetSuite Order Link - ' . $key,
                        'content' => 
                            Html::A($key, "https://{$AccountID}.app.netsuite.com/app/accounting/transactions/salesord.nl?id={$value}&whence=", [
                            'target' => '_blank',
                            'class' => 'btn btn-sm btn-outline-primary'
                            ])
                    ];
                }
                
            });
        Event::on(
            View::class,
            'cart-view-buttons-after', 
            function($event){
                if(Yii::$app->user->identity->inGroup('Global Admins') || Yii::$app->user->identity->inGroup('Sales Admin')){
                    echo  Html::tag('li', Html::Button(Yii::t('app', 'Send to Netsuite'), ['class' => 'nav-link btn bg-success text-white w-100 mb-1', 'id' => 'sendtonetsuite']), ['class' => 'nav-item']);
                    echo  Html::tag('li', Html::Button(Yii::t('app', 'Link to Netsuite'), ['class' => 'nav-link btn bg-success text-white w-100 mb-1 link-netsuite-order']), ['class' => 'nav-item']);
                }
            }
        );
        Event::on(
            View::class,
            'cart-update-tabs-after', 
            function($event){
                $event->buttons[] = [
                    'label' => 'NetSuite Integration',
                    'content' => Yii::$app->view->render('@PortalPeople/netsuite/views/cart/viewtabs/_netsuite_integration_tab', ['model' => $event->model]),
                ];
            }
        );
        Event::on(
            View::class,
            'products-update-tabs-after', 
            function($event){
                $event->customData[] = [
                    'label' => 'NetSuite Integration',
                    'content' => Yii::$app->view->render('@PortalPeople/netsuite/views/products/update', ['model' => $event->model]),
                ];
            }
        );
        Event::on(
            View::class,
            'products-view-tabs-after', 
            function($event){
                $event->customData[] = [
                    'label' => 'NetSuite Integration',
                    'content' => Yii::$app->view->render('@PortalPeople/netsuite/views/products/view', ['model' => $event->model]),
                ];
            }
        );
        
        Yii::$app->on('cart-order-sendtonetsuite-queue', function ($event) {
                \Yii::$app->netsuitequeue
                    ->jobname('Send to ERP (NetSuite)')    
                    ->relatedid($this->id)    
                    ->delay(120)
                    ->ttr(300)
                    ->push(new \portalpeople\netsuite\jobs\Sendtonetsuite(['id' => $this->id]));

        });
        Yii::$app->on('cart-order-sendtonetsuite', function ($event) {
            \PortalPeople\netsuite\components\NetSuite::SendOrderToNetsuite($event->model->id);
        });
        Yii::$app->on('cartsbe-afterSave-end', function ($event) {
           /* $cart = $event->model;
            if($cart->status == 'Paid' && is_object($cart->shipment) == true){
                    $shippingcosts = \PortalPeople\shippingcosts\models\Shippingcosts::costs($cart->id);
                    $count = count($shippingcosts);
                    if($count > 1){
                        foreach($shippingcosts as $haulier => $data){
                            $cartline = \backend\models\Cartlines::find()
                                ->where(['basketid' => $cart->id, 'haulierint' => $haulier, 'productid' => '331D4D9B-7F11-9473-1279-CAFDA629360A'])
                            ->one();
                            if (!$cartline){
                                $cartline = new \backend\models\Cartlines(['id' => \backend\models\Cartlines::Tempid(), 'basketid' => $cart->id]);
                                $cartline->productid = '331D4D9B-7F11-9473-1279-CAFDA629360A';
                                $cartline->requested_date = $cart->shippingline->requested_date;
                                $cartline->haulierint = $haulier;
                                $cartline->qty = 1;
                                $cartline->erpqty = 1;
                                $cartline->price = 0;
                                $cartline->linetotal = 0.00;
                                $cartline->deliveryline = 0;
                                $cartline->paid = true;
                            } 
                            $cartline->cost = $data['cost'];
                            $cartline->product_description = $cart->shippingline->product_description;
                            $cartline->hidden_info = $data['haulier'].' Delivery ' . \yii\helpers\Inflector::pluralize($data['pallets'] . ' Pallet');
                            $cartline->save();
                        }   
                    }  elseif($count == 1){
                        foreach($shippingcosts as $haulier => $data){
                            $cartline = \backend\models\Cartlines::find()
                                ->where(['basketid' => $cart->id, 'productid' => '331D4D9B-7F11-9473-1279-CAFDA629360A'])
                                ->one();
                            if ($cartline){
                                $cartline->haulierint = $haulier;
                                $cartline->cost = $data['cost'];
                                $cartline->product_description = $cart->shippingline?->product_description;
                                $cartline->hidden_info = $data['haulier'].' Delivery ' . \yii\helpers\Inflector::pluralize($data['pallets'] . ' Pallet');
                                $cartline->save();
                            }
                        }
                    }
                }   */
        });
    }
}