<?php

namespace PortalPeople\shippingcosts\models;

use Yii;
use yii\base\Model;

class ConfigForm extends Model
{
    public $enabled = true;
    public $maxShippingCost = 1000.00;
    public $defaultHaulierId;
    public $debug = false;
    public $parametersJson = '[]';

    public function rules(): array
    {
        return [
            [['enabled', 'debug'], 'boolean'],
            [['maxShippingCost'], 'number', 'min' => 0],
            [['defaultHaulierId'], 'integer', 'min' => 0],
            [['parametersJson'], 'string'],
            [['parametersJson'], 'validateParametersJson'],
        ];
    }

    public function attributeLabels(): array
    {
        return [
            'enabled' => 'Enable Shipping Costs Module',
            'maxShippingCost' => 'Maximum Shipping Cost',
            'defaultHaulierId' => 'Default Haulier ID',
            'debug' => 'Enable Debug Logging',
            'parametersJson' => 'Parameter Controls',
        ];
    }

    public function attributeHints(): array
    {
        return [
            'maxShippingCost' => 'Upper cap used by shipping calculations and safety checks.',
            'defaultHaulierId' => 'Optional fallback haulier when no direct route match is found.',
            'parametersJson' => 'Managed by the parameter controls editor below.',
        ];
    }

    public function validateParametersJson(string $attribute): void
    {
        $decoded = json_decode((string) $this->$attribute, true);

        if (json_last_error() !== JSON_ERROR_NONE || !is_array($decoded)) {
            $this->addError($attribute, 'Parameters JSON is invalid.');
            return;
        }

        foreach ($decoded as $index => $row) {
            if (!is_array($row)) {
                $this->addError($attribute, 'Each parameter row must be an object.');
                return;
            }

            $key = trim((string) ($row['key'] ?? ''));
            if ($key === '') {
                $this->addError($attribute, 'Each parameter must include a key.');
                return;
            }

            $type = (string) ($row['type'] ?? 'text');
            if (!in_array($type, ['text', 'number', 'boolean', 'select'], true)) {
                $this->addError($attribute, "Unsupported parameter type at row " . ($index + 1) . '.');
                return;
            }
        }
    }

    public function loadFromParams(): bool
    {
        $config = Yii::$app->params['plugins']['shippingcosts'] ?? null;

        if (!is_array($config)) {
            $this->parametersJson = json_encode($this->getDefaultParameters(), JSON_PRETTY_PRINT);
            return false;
        }

        $this->enabled = (bool) ($config['enabled'] ?? $this->enabled);
        $this->maxShippingCost = (float) ($config['maxShippingCost'] ?? $this->maxShippingCost);
        $this->defaultHaulierId = isset($config['defaultHaulierId']) ? (int) $config['defaultHaulierId'] : null;
        $this->debug = (bool) ($config['debug'] ?? $this->debug);

        $parameters = $config['parameters'] ?? $this->getDefaultParameters();
        $this->parametersJson = json_encode($this->normalizeParameters($parameters), JSON_PRETTY_PRINT);

        return true;
    }

    public function saveToParams(): bool
    {
        try {
            $paramsFile = Yii::getAlias('@backend/config/params-local.php');
            $params = file_exists($paramsFile) ? include $paramsFile : [];

            if (!is_array($params)) {
                $params = [];
            }

            if (!isset($params['plugins']) || !is_array($params['plugins'])) {
                $params['plugins'] = [];
            }

            $decoded = json_decode((string) $this->parametersJson, true);
            $defaultHaulierId = $this->defaultHaulierId === null || $this->defaultHaulierId === ''
                ? null
                : (int) $this->defaultHaulierId;

            $params['plugins']['shippingcosts'] = [
                'enabled' => (bool) $this->enabled,
                'maxShippingCost' => (float) $this->maxShippingCost,
                'defaultHaulierId' => $defaultHaulierId,
                'debug' => (bool) $this->debug,
                'parameters' => $this->normalizeParameters(is_array($decoded) ? $decoded : []),
            ];

            $content = "<?php\n\nreturn " . var_export($params, true) . ";\n";
            return file_put_contents($paramsFile, $content) !== false;
        } catch (\Throwable $throwable) {
            Yii::error('Failed to save shippingcosts config: ' . $throwable->getMessage(), 'shippingcosts');
            return false;
        }
    }

    public function getParameterRows(): array
    {
        $decoded = json_decode((string) $this->parametersJson, true);
        if (!is_array($decoded) || $decoded === []) {
            return $this->getDefaultParameters();
        }

        return $this->normalizeParameters($decoded);
    }

    private function normalizeParameters(array $parameters): array
    {
        $out = [];

        foreach ($parameters as $row) {
            if (!is_array($row)) {
                continue;
            }

            $key = trim((string) ($row['key'] ?? ''));
            if ($key === '') {
                continue;
            }

            $type = (string) ($row['type'] ?? 'text');
            if (!in_array($type, ['text', 'number', 'boolean', 'select'], true)) {
                $type = 'text';
            }

            $out[] = [
                'key' => $key,
                'label' => trim((string) ($row['label'] ?? $key)),
                'type' => $type,
                'default' => (string) ($row['default'] ?? ''),
                'options' => trim((string) ($row['options'] ?? '')),
                'required' => (bool) ($row['required'] ?? false),
                'enabled' => (bool) ($row['enabled'] ?? true),
            ];
        }

        return $out;
    }

    private function getDefaultParameters(): array
    {
        return [
            [
                'key' => 'max_shipping_cost',
                'label' => 'Max Shipping Cost',
                'type' => 'number',
                'default' => '1000',
                'options' => '',
                'required' => true,
                'enabled' => true,
            ],
            [
                'key' => 'shipping_promotion',
                'label' => 'Shipping Promotion Text',
                'type' => 'text',
                'default' => '',
                'options' => '',
                'required' => false,
                'enabled' => true,
            ],
            [
                'key' => 'zero_cost_shipping',
                'label' => 'Zero Cost Shipping Threshold',
                'type' => 'number',
                'default' => '0',
                'options' => '',
                'required' => false,
                'enabled' => true,
            ],
        ];
    }
}
