<?php
/**
 * i-doit - Documentation and CMDB solution for IT environments
 *
 * This file is part of the i-doit framework. Modify at your own risk.
 *
 * Please visit http://www.i-doit.com/license for a full copyright and license information.
 *
 * @version     1.10
 * @package     i-doit
 * @author      synetics GmbH
 * @copyright   synetics GmbH
 * @url         http://www.i-doit.com
 * @license     http://www.i-doit.com/license
 */

namespace idoit\Console\Command\Workflow;

use idoit\Console\Command\AbstractCommand;
use isys_cmdb_dao_category_g_contact;
use isys_cmdb_dao_category_g_contract_assignment;
use isys_cmdb_dao_category_s_contract;
use isys_contact_dao_reference;
use isys_helper_link;
use isys_locale;
use isys_tenantsettings;
use isys_workflow_action_assign;
use isys_workflow_dao_action;
use isys_workflow_dao_dynamic;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MaintenanceCommand extends AbstractCommand
{
    const NAME = 'system-maintenancecontract';
    const TITLE = 'Maintenance timeout: %s';

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * Get name for command
     *
     * @return string
     */
    public function getCommandName()
    {
        return self::NAME;
    }

    /**
     * Get description for command
     *
     * @return string
     */
    public function getCommandDescription()
    {
        return 'Sends e-mail notifications for maintenance contracts (Function is deprecated, please use the notification add-on)';
    }

    /**
     * Retrieve Command InputDefinition
     *
     * @return InputDefinition
     */
    public function getCommandDefinition()
    {
        $definition = new InputDefinition();

        return $definition;
    }

    /**
     * Checks if a command can have a config file via --config
     *
     * @return bool
     */
    public function isConfigurable()
    {
       return true;
    }

    /**
     * Returns an array of command usages
     *
     * @return string[]
     */
    public function getCommandUsages()
    {
        return [];
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if (!defined("C__MAINT__NOT_DAYS"))
        {
            define("C__MAINT__NOT_DAYS", "+0");
        } // if

        $this->output = $output;

        $this->output->writeln('<error>system-maintenancecontract is deprecated, please do not use it anymore!</error>');

        $this->output->writeln("Maintenance-Handler initialized (" . date("Y-m-d H:i:s") . ")");
        $this->output->writeln("Starting parser..");

        try {
            $this->parse();
        } catch (\Exception $exception) {
            $this->output->writeln('<error>' . $exception->getMessage() . '</error>');
        }
    }

    /**
     * Match date
     *
     * @return boolean
     */
    public function check()
    {
        return false;
    }

    /**
     * @return bool
     */
    public function parse()
    {
        // Get all specific contracts.
        $this->output->writeln("Parsing contract objects..");
        $l_cats_dao  = new isys_cmdb_dao_category_s_contract($this->container->database);
        $l_contracts = $l_cats_dao->get_data(null, null, "AND (isys_obj__status != " . C__RECORD_STATUS__TEMPLATE . ")");

        if ($l_contracts->num_rows() > 0)
        {
            $this->output->writeln(" Found " . $l_contracts->num_rows());

            while ($l_row = $l_contracts->get_row())
            {

                if (!empty($l_row["isys_cats_contract_list__end_date"]))
                {
                    $l_end = strtotime($l_row["isys_cats_contract_list__end_date"]);

                    /**
                     * @todo nachfragen
                     */
                    if (date("Ymd", strtotime(C__MAINT__NOT_DAYS . " days")) == date("Ymd", $l_end))
                    {

                        $l_title       = $l_cats_dao->get_obj_name_by_id_as_string($l_row["isys_cats_contract_list__isys_obj__id"]);
                        $l_description = $this->get_description_s($l_title, $l_row);

                        $this->output->writeln(
                            "Timeout detected: " . $l_title . " / " . isys_locale::get_instance()->fmt_date(
                                $l_row["isys_cats_contract_list__end_date"]
                            ) . " - Notificating..."
                        );

                        

                        $l_title = sprintf(self::TITLE, $l_title);
                        if ($this->create_task($l_title, $l_description, $l_row["isys_cats_contract_list__isys_obj__id"]))
                        {
                            $this->output->writeln("done");
                        }
                        else $this->output->writeln("failed");
                    }
                }

            }
        }
        else
        {
            $this->output->writeln("Nothing found");
        }

        /* Get all global contracts */
        $this->output->writeln("Parsing regular objects with sub-contracts..");
        $l_catg_dao  = new isys_cmdb_dao_category_g_contract_assignment($this->container->database);
        $l_contracts = $l_catg_dao->get_data(null, null, "AND (isys_obj__status != " . C__RECORD_STATUS__TEMPLATE . ")");

        if ($l_contracts->num_rows() > 0)
        {
            $this->output->writeln(" Found " . $l_contracts->num_rows());

            while ($l_row = $l_contracts->get_row())
            {

                if (!empty($l_row["isys_catg_contract_assignment_list__contract_end "]) || !empty($l_row["isys_cats_contract_list__end_date"]))
                {
                    $l_end = (!empty($l_row["isys_catg_contract_assignment_list__contract_end"])) ? $l_row["isys_catg_contract_assignment_list__contract_end"] : $l_row["isys_cats_contract_list__end_date"];
                    $l_end = strtotime($l_end);

                    if (date("Ymd", strtotime(C__MAINT__NOT_DAYS . " days")) == date("Ymd", $l_end))
                    {

                        $l_title = $l_catg_dao->get_obj_name_by_id_as_string(
                                $l_row["isys_catg_contract_assignment_list__isys_obj__id"]
                            ) . " (" . $l_row["isys_catg_contract_assignment_list__title"] . ")";

                        $l_description = $this->get_description_g($l_title, $l_row);

                        $this->output->writeln(
                            "Timeout detected: " . $l_title . " / " . isys_locale::get_instance()->fmt_date(
                                $l_end
                            ) . " - Notificating..."
                        );
                        

                        $l_title = sprintf(self::TITLE, $l_title);
                        if ($this->create_task($l_title, $l_description, $l_row["isys_catg_contract_assignment_list__isys_obj__id"]))
                        {
                            $this->output->writeln("done");
                        }
                        else $this->output->writeln("failed");

                    }
                }

            }
        }
        else
        {
            $this->output->writeln("Nothing found");
        }

        return true;
    }

    /**
     * @param $p_title
     * @param $p_row
     *
     * @return string
     */
    private function get_description_s($p_title, $p_row)
    {
        $l_start = isys_locale::get_instance()->fmt_date($p_row["isys_cats_contract_list__start_date"]);
        $l_end   = isys_locale::get_instance()->fmt_date($p_row["isys_cats_contract_list__end_date"]);

        $l_params = [
            C__CMDB__GET__OBJECT   => $p_row["isys_cats_contract_list__isys_obj__id"],
            C__CMDB__GET__CATS     => C__CATS__CONTRACT,
            C__CMDB__GET__TREEMODE => C__CMDB__VIEW__TREE_OBJECT,
            C__CMDB__GET__VIEWMODE => C__CMDB__VIEW__CATEGORY_GLOBAL,
            C__CMDB__GET__CATLEVEL => $p_row["isys_cats_contract_list__id"]

        ];

        $l_str_link = '<a href="' . isys_helper_link::create_url($l_params) . '" target="_new">' . $p_title . '</a>';

        return sprintf(
            C__WORKFLOW_MSG__MAINTENANCE,
            $l_str_link,
            $l_start,
            $l_end,
            $p_row["isys_cats_contract_list__support_url"],
            $p_row["isys_cats_contract_list__contract_no"],
            $p_row["isys_cats_contract_list__customer_no"]
        );
    }

    /**
     * @param $p_title
     * @param $p_row
     *
     * @return string
     */
    private function get_description_g($p_title, $p_row)
    {
        $l_start = isys_locale::get_instance()->fmt_date($p_row["isys_catg_contract_assignment_list__contract_start"]);
        $l_end   = isys_locale::get_instance()->fmt_date($p_row["isys_catg_contract_assignment_list__contract_end"]);

        $l_params = [
            C__CMDB__GET__OBJECT   => $p_row["isys_catg_contract_assignment_list__isys_obj__id"],
            C__CMDB__GET__CATG     => C__CATG__CONTRACT_ASSIGNMENT,
            C__CMDB__GET__TREEMODE => C__CMDB__VIEW__TREE_OBJECT,
            C__CMDB__GET__VIEWMODE => C__CMDB__VIEW__CATEGORY_GLOBAL,
            C__CMDB__GET__CATLEVEL => $p_row["isys_catg_contract_assignment_list__id"]

        ];

        $l_str_link    = '<a href="' . isys_helper_link::create_url($l_params) . '" target="_new">' . $p_title . '</a>';
        $l_empty_value = isys_tenantsettings::get('gui.empty_value', '-');

        return sprintf(
            C__WORKFLOW_MSG__MAINTENANCE,
            $l_str_link,
            $l_start,
            $l_end,
            $l_empty_value,
            $l_empty_value,
            $l_empty_value
        );
    } // function

    /**
     * Creates a task with title $p_title and $p_description
     * and notifies the contacts, which are assigned to $p_object_id
     *
     * @param string $p_title
     * @param string $p_description
     * @param int    $p_object_id
     *
     * @return int workflow id
     */
    protected function create_task($p_title, $p_description, $p_object_id)
    {
        if (empty($p_object_id)) return false;

        $l_object_id   = $p_object_id;
        $l_description = $p_description;

        $l_wf_action_dao = new isys_workflow_dao_action($this->container->database);
        $l_dao_dynamic   = new isys_workflow_dao_dynamic($this->container->database);
        $l_contact_to    = new isys_contact_dao_reference($this->container->database);
        $l_contact_from  = new isys_contact_dao_reference($this->container->database);
        $l_catg_contact  = new isys_cmdb_dao_category_g_contact($this->container->database);

        /* Get all contacts assigned to $l_object_id */
        $l_contacts = $l_catg_contact->get_contacts_by_obj_id($l_object_id);
        if ($l_contacts->num_rows() > 0)
        {
            while ($l_row = $l_contacts->get_row())
            {
                $l_persons[] = $l_row["isys_cats_person_list__isys_obj__id"];
            }
        }
        else
        {
            $this->output->writeln("No contacts assigned. ", false);

            return false;
        }

        if (isset($l_persons))
        {
            $l_contact_to->ref_contact($l_persons);
            if ($l_contact_to->save()) $l_contact_to_id = $l_contact_to->get_id();

        }
        else $l_contact_to_id = null;

        /* Reference myself */
        $l_contact_from->ref_contact([$this->session->get_user_id()]);
        $l_contact_from->save();

        if (!($l_workflow_id = $l_dao_dynamic->create_workflow(
            $p_title,
            $l_contact_from->get_id(),
            C__WORKFLOW_TYPE__TASK,
            null,
            $l_object_id
        ))
        )
        {
            return false;
        }

        $l_action_new_id = $l_wf_action_dao->create_action(C__WORKFLOW__ACTION__TYPE__NEW);

        if ($l_action_new_id > 0)
        {
            $l_wf_action_dao->bind($l_workflow_id, $l_action_new_id);

            $l_wf_action_dao->add_parameter($l_action_new_id, C__WF__PARAMETER_TYPE__DATETIME, "task__start_date", date("Y-m-d"), 1);

            $l_wf_action_dao->add_parameter($l_action_new_id, C__WF__PARAMETER_TYPE__TEXT, "task__description", $l_description, 3);
        } // if

        if (isset($l_contact_to_id) && is_numeric($l_contact_to_id))
        {
            $l_assign = new isys_workflow_action_assign();
            $l_assign->save($l_workflow_id, $l_contact_to_id);
        } // if

        $this->output->writeln('Created workflow task: ' , $l_workflow_id);

        return $l_workflow_id;
    } // function
}
