<?php

namespace PortalPeople\shippingcosts\models;

use Yii;
use backend\models\Accounts;
use PortalPeople\shippingcosts\models\Shippingcostsprices;
use yii\helpers\Json;
use PortalPeople\shippingcosts\services\PostcodeExpansionService;
use PortalPeople\shippingcosts\services\ShippingCostCalculatorService;

/**
 * Shippingcosts Model - Database model for shipping costs.
 * 
 * This model delegates business logic to service classes:
 * - PostcodeExpansionService: Postcode expansion logic
 * - ShippingCostCalculatorService: Shipping cost calculations
 *
 * @property string $id
 * @property string $language
 * @property string|null $created_by
 * @property string|null $updated_by
 * @property string|null $deleted_by
 * @property string|null $relatedid
 * @property string|null $centerid
 * @property int|null $created_at
 * @property int|null $updated_at
 * @property int|null $deleted_at
 * @property string|null $status
 * @property string|null $createdby_name
 * @property string|null $updatedby_name
 * @property string|null $deletedby_name
 * @property string|null $type
 * @property int|null $haulierid
 * @property float|null $price
 * @property string|null $postcodes
 * @property string|null $notes
 */
class Shippingcosts extends \common\models\Base
{
    public $dates = [];
    public $uniqueidentifiers = [];
    public $securefields = [];
    public $pricea = 0.00;
    public $priceqty = 0;
    public $types = [];
    public bool $regen = false;

    public static function tableName()
    {
        return 'shipping_costs';
    }

    public function rules()
    {
        return [
            [['created_at', 'updated_at', 'deleted_at'], 'safe'],
            [['postcodes', 'notes', 'price'], 'string'],
            [['haulierid', 'no_of_prices'], 'integer'],
            [['prices'], 'safe'],
            [['regen'], 'boolean'],
            [['id', 'created_by', 'updated_by', 'deleted_by', 'relatedid', 'centerid'], 'string', 'max' => 36],
            [['language'], 'string', 'max' => 10],
            [['status', 'createdby_name', 'updatedby_name', 'deletedby_name', 'type'], 'string', 'max' => 255],
            [['types'], 'safe'],
            ['id', 'default', 'value' => parent::Tempid()],
            ['language', 'default', 'value' => 'en'],
            ['no_of_prices', 'default', 'value' => 0],
            ['status', 'default', 'value' => 'Active'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'id'),
            'language' => Yii::t('app', 'language'),
            'created_by' => Yii::t('app', 'Created By'),
            'updated_by' => Yii::t('app', 'Updated By'),
            'deleted_by' => Yii::t('app', 'Deleted By'),
            'relatedid' => Yii::t('app', 'Related ID'),
            'centerid' => Yii::t('app', 'Center ID'),
            'created_at' => Yii::t('app', 'Created At'),
            'updated_at' => Yii::t('app', 'Updated At'),
            'deleted_at' => Yii::t('app', 'Deleted At'),
            'status' => Yii::t('app', 'Status'),
            'createdby_name' => Yii::t('app', 'Created By Name'),
            'updatedby_name' => Yii::t('app', 'Updated By Name'),
            'deletedby_name' => Yii::t('app', 'Deleted By Name'),
            'type' => Yii::t('app', 'Shipping Type'),
            'types' => Yii::t('app', 'Shipping Types'),
            'haulierid' => Yii::t('app', 'Haulier ID'),
            'prices' => Yii::t('app', 'Price'),
            'no_of_prices' => Yii::t('app', 'No of Prices'),
            'postcodes' => Yii::t('app', 'Post Codes Range'),
            'notes' => Yii::t('app', 'Notes'),
            'regen' => Yii::t('app', 'Re-Generate'),
        ];
    }

    public function getHaulier()
    {
        return $this->hasOne(Accounts::class, ['intid' => 'haulierid']);
    }

    public function beforeSave($save)
    {
        $this->type = match($this->type){
            'ECON' => 'Eco',
            'PREM' => 'Next Day',
            default => $this->type
        };
        //$this->type = json_encode($this->types); // Ensure type is an array for processing
        // Delegate postcode processing to service
        if (Yii::$app->controller->action->id == 'create' || $this->regen == true) {

            if (is_array($this->postcodes)) {
                $this->postcodes = implode('||', PostcodeExpansionService::expandPostcodes($this->postcodes));
            }
        }

        // Handle prices array - merge existing with new
        if ($this->no_of_prices > 0) {
            $prices = [];
            $existing = is_array($this->prices) ? $this->prices : [];
            $count = count($existing);
            
            while ($count < $this->no_of_prices) {
                $prices[] = [];
                $count++;
            }
            
            $this->prices = !empty($prices) ? Json::encode(array_merge($existing, $prices)) : Json::encode($existing);
        }

        return parent::beforeSave($save);
    }

    public function afterFind()
    {
        // Parse JSON prices into form models for loadMultiple/validateMultiple support.
        if ($this->prices && is_string($this->prices)) {
            $decoded = Json::decode($this->prices, true);
            if (is_array($decoded)) {
                $pricingModels = [];
                foreach ($decoded as $priceDetails) {
                    $price = new Shippingcostsprices();
                    if (is_array($priceDetails)) {
                        $price->attributes = $priceDetails;
                    }
                    $pricingModels[] = $price;
                }
                $this->prices = $pricingModels;
            }
        }
        return parent::afterFind();
    }

    /**
     * DEPRECATED: Use PostcodeExpansionService::expandPostcodes() instead.
     * @deprecated
     */
    public static function processpostcodes($codes)
    {
        return PostcodeExpansionService::expandPostcodes($codes);
    }

    /**
     * DEPRECATED: Use ShippingCostCalculatorService::calculateCartCosts() instead.
     * @deprecated
     */
    public static function costs($id, $method = null): ?array
    {
        return ShippingCostCalculatorService::calculateCartCosts($id, $method);
    }
}
