<?php 
namespace modules\hse\models;

use Yii;
use yii\data\{ActiveDataProvider, ArrayDataProvider};
use yii\base\Model;
use modules\activities\models\Activities;

class FatigueCalculatorSearch extends \modules\activities\models\Activities
{
    public $user;
    public $start_date;
    public $end_date;
    
    public function rules(): array
    {
        return array_merge(parent::rules(), [
            [['user', 'start_date', 'end_date'], 'safe'],
        ]);
    }


    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }


    public function search($params)
    {
        $this->load($params);
        
        $fatigue = new \yii\db\Expression("json_extract(data, '$.Fatigue')");
        $query = \modules\activities\models\Activities::find()
            ->where(['not', ['jobstatus' => ['Lodge']]])
            ->andWhere(['not', ['is', $fatigue, null]]);
        
        // Apply date filters if set, otherwise default to last 30 days
        if ($this->start_date) {
            $query->andWhere(['>=', 'sdate', $this->start_date]);
        } else {
            $query->andWhere(['>=', 'sdate', date('Y-m-d', strtotime('-30 days'))]);
        }
        
        if ($this->end_date) {
            $query->andWhere(['<=', 'sdate', $this->end_date . ' 23:59:59']);
        }

        $query = $query->select([
            'activities.*',
            new \yii\db\Expression("json_extract(data, '$.Fatigue') as fatigue_data")
        ]);

        // Split query to expand fatigue array entries into multiple rows
        // First, we need to get the keys from the fatigue object and create rows for each key
        $query = Activities::find()
            ->from(['activities' => $query])
            ->select([
                'activities.id',
                'activities.sdate',
                'activities.edate',
                'activities.comments',
                'activities.data',
                new \yii\db\Expression("numbers.n as fatigue_index"),
                new \yii\db\Expression("date(`sdate`) as date"),
                new \yii\db\Expression("time(`sdate`) as start_time"),
                new \yii\db\Expression("time(`edate`) as end_time"),
                new \yii\db\Expression("TIMESTAMPDIFF(MINUTE, `sdate`, `edate`) / 60 as duty_length"),
                new \yii\db\Expression("JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(activities.fatigue_data), CONCAT('$[', numbers.n, ']'))) as fatigue_key"),
                new \yii\db\Expression("JSON_EXTRACT(activities.fatigue_data, CONCAT('$.\"', JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(activities.fatigue_data), CONCAT('$[', numbers.n, ']'))), '\"')) as fatigue_entry"),
                // Extract individual properties using the dynamic key
                new \yii\db\Expression("JSON_UNQUOTE(JSON_EXTRACT(activities.fatigue_data, CONCAT('$.\"', JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(activities.fatigue_data), CONCAT('$[', numbers.n, ']'))), '\".intensity'))) as work_intensity"),
                new \yii\db\Expression("JSON_UNQUOTE(JSON_EXTRACT(activities.fatigue_data, CONCAT('$.\"', JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(activities.fatigue_data), CONCAT('$[', numbers.n, ']'))), '\".user'))) as user"),
                new \yii\db\Expression("JSON_UNQUOTE(JSON_EXTRACT(activities.fatigue_data, CONCAT('$.\"', JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(activities.fatigue_data), CONCAT('$[', numbers.n, ']'))), '\".commutetime'))) as commutetime"),
            ])
            ->innerJoin(
                '(SELECT 0 as n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19) as numbers',
                new \yii\db\Expression("numbers.n < JSON_LENGTH(JSON_KEYS(activities.fatigue_data))")
            )->orderby(['sdate' => SORT_ASC]);
        $this->load($params);

        // Get results as array
        $results = $query->asArray()->all();
        // Apply user filter if set
        if ($this->user) {
            $results = array_filter($results, function($row) {
                return $row['user'] == $this->user;
            });
        }
        // add conditions that should always apply here
        foreach($results as $key => $row) {
            $default = (\modules\users\models\User::find()->where(['username' => $row['user']])->one());
            $FatigueRisk = ($default && isset($default->data['FatigueRisk'])) ? $default->data['FatigueRisk'] : null;
            //->data->FatigueRisk->typical_commuting_time;
            if ($FatigueRisk) {
                $results[$key]['commutetime'] = empty($row['commutetime']) ? $FatigueRisk['typical_commuting_time_minutes'] : $row['commutetime'];
                // $results[$key]['work_intensity'] = empty($row['work_intensity']) ? $FatigueRisk['work_intensity'] : $row['work_intensity'];
            } else {
                $results[$key]['commutetime'] = $row['commutetime'];
                // $results[$key]['work_intensity'] = $row['work_intensity'];
            }
        }
        
        $dataProvider = new ArrayDataProvider([
            'allModels' => $results,
            'pagination' => false,
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'created_at' => $this->created_at,
            'created_by' => $this->created_by,
            'updated_at' => $this->updated_at,
            'updated_by' => $this->updated_by,
        ]);


        return $dataProvider;
    }
}