<?php

namespace objects;

use classes\db;
use classes\object_property;
use classes\selfserve;
use Exception;
use goals\classes\goals_criteria;
use traits\db_object_t;

class department_goals_o extends db
{
    use db_object_t;
    public object_property $created_by; // The user_id who created the goal
    public object_property $name; // The name of the goal
    public object_property $departments; // A JSON with the department ids
    public object_property $criteria; // A JSON with the criteria object
    public object_property $created_at;
    public object_property $updated_at;
    public object_property $deleted_at;


    public function structure(): void
    {
        $this->setTable('goals');
    }

    /**
     * Add a goal
     * @param users_o $created_by The user id who created the goal
     * @param departments_o[] $departments The departments for the goal
     * @param goals_criteria $criteria The criteria object
     * @return department_goals_o
     * @throws Exception If the object was not created successfully
     */
    public function add(users_o $created_by, array $departments, goals_criteria $criteria): department_goals_o
    {
        // Sanitize the input
        $created_by->requireSelected();
        foreach ($departments as $dept) {
            $dept->requireSelected();
        }
        // Validate and sanitize criteria object
        $criteria->validateAndSanitize();
        // Add the object
        $tmp_id = self::add_object([
            'created_by' => (int)$created_by->id,
            'departments' => array_map(fn($dept) => (int)$dept->id, $departments),
            'criteria' => (array)$criteria->toArray(),
        ]);
        $this->id = $tmp_id;
        self::getObjectProperties();
        self::objectChanged();
        return $this;
    }



    public function getObjectProperties(): void
    {
        $this->created_by = new object_property($this->table, $this->id, 'created_by', 'int', false);
        $this->departments = new object_property($this->table, $this->id, 'departments', 'json', false);
        $this->criteria = new object_property($this->table, $this->id, 'criteria', 'json', false);
        $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
        $this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
        $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
    }

    public function objectChanged(): void
    {
        //TODO: Add cache invalidation
    }

    /**
     * @throws Exception
     */
    public function asArray($include_progress = true): array
    {
        return [
            'id' => (int)$this->id,
            'created_by' => (int)$this->created_by->value(),
            'departments' => (array)$this->departments->value(),
            'criteria' => (array)$this->criteria->value(),
            'progress' => [
                'value' => $include_progress ? goals_criteria::calculateProgressFromArray((array)$this->criteria->value()) : null,
                'departmental_distribution' => $include_progress ? goals_criteria::calculateDepartmentalProgressFromArray((array)$this->criteria->value()) : null,
            ],
            'created_at' => (string)$this->created_at->value(),
            'updated_at' => (string)$this->updated_at->value(),
        ];
    }
}