<?php

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");
        }

        $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);
    }

    /**
     * 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 (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);
        }

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

        return $l_workflow_id;
    }
}
