/*
** Job Arranger for ZABBIX
** Copyright (C) 2025 Daiwa Institute of Research Ltd. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

package main

import (
	zbxlink "jobarranger2/src/jobarg_server/managers/zabbix_link_manager/zbx_link"
	"jobarranger2/src/libs/golibs/database"
)

const (
	/* zabbix flag discovery */
	ZBXLINK_FLAG_DISCOVERY_NORMAL  = 0
	ZBXLINK_FLAG_DISCOVERY_CREATED = 4

	/* zabbix host status */
	ZBXLINK_HOST_STATUS_MONITORED     = 0
	ZBXLINK_HOST_STATUS_NOT_MONITORED = 1

	/* zabbix item */
	ZBXLINK_NON_TARGET_ITEM_TYPE = 9
)

type Updater struct {
	DB database.DBConnection
}

func NewUpdater(dbConn database.DBConnection) zbxlink.ZabbixUpdater {
	return &Updater{
		DB: dbConn,
	}
}

func (dbUpdater *Updater) GetHostId(groupId string) (database.DBresult, error) {
	result, err := dbUpdater.DB.Select(
		"select distinct h.hostid from hosts h, hosts_groups hg where h.flags in(%d, %d) and hg.groupid = %s and hg.hostid = h.hostid and h.status in(%d, %d)",
		ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED, groupId,
		ZBXLINK_HOST_STATUS_MONITORED, ZBXLINK_HOST_STATUS_NOT_MONITORED,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// SetHostStatus implements ZabbixUpdater.
func (dbUpdater *Updater) SetHostStatus(hostId string, status int) error {
	_, err := dbUpdater.DB.Execute(
		"update hosts set status = ? where hostid = ? and status in(?, ?) and flags in(?, ?)",
		status, hostId, ZBXLINK_HOST_STATUS_MONITORED, ZBXLINK_HOST_STATUS_NOT_MONITORED, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		/* hosts table update failure */
		return err
	}
	return nil
}

// GetHostStatus implements zbxlink.ZabbixUpdater.
func (dbUpdater *Updater) GetHostStatus(hostId string) (database.DBresult, error) {
	/* hosts table search */
	result, err := dbUpdater.DB.Select(
		"select status from hosts where hostid = %s and status in(%d, %d) and flags in(%d, %d)",
		hostId, ZBXLINK_HOST_STATUS_MONITORED, ZBXLINK_HOST_STATUS_NOT_MONITORED,
		ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (dbUpdater *Updater) SetItemStatus(itemId string, status int) error {
	_, err := dbUpdater.DB.Execute(
		"update items set status = ? where itemid = ? and type <> ? and flags in(?, ?)",
		status, itemId, ZBXLINK_NON_TARGET_ITEM_TYPE, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		/* items table update failure */
		return err
	}
	return nil
}

func (dbUpdater *Updater) GetItemStatus(itemId string) (database.DBresult, error) {
	/* items table search */
	result, err := dbUpdater.DB.Select(
		"select items.status,item_rtdata.state from items,item_rtdata where items.itemid = %s and item_rtdata.itemid =items.itemid and items.type <> %d and items.flags in(%d, %d)",
		itemId, ZBXLINK_NON_TARGET_ITEM_TYPE, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (dbUpdater *Updater) GetItemData(getItemId string) (database.DBresult, error) {
	result, err := dbUpdater.DB.Select(
		"select itemid, value_type from items where itemid = %s and type <> %d and flags in(%d, %d)",
		getItemId, ZBXLINK_NON_TARGET_ITEM_TYPE, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (dbUpdater *Updater) GetHistoryData(getItemId string, valueType int) (database.DBresult, error) {
	var historyTblName = []string{
		"history",
		"history_str",
		"history_log",
		"history_uint",
		"history_text",
	}

	result, err := dbUpdater.DB.Select(
		"select value from %s where itemid = %s order by clock desc limit 1 offset 0",
		historyTblName[valueType], getItemId,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (dbUpdater *Updater) SetTriggerStatus(triggerId string, status int) error {
	_, err := dbUpdater.DB.Execute(
		"update triggers set status = ? where triggerid = ? and flags in(?, ?)",
		status, triggerId, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	/* triggers table update failure */
	if err != nil {
		return err
	}
	return nil
}

// GetTriggerStatus implements zbxlink.ZabbixUpdater.
func (dbUpdater *Updater) GetTriggerStatus(triggerId string) (database.DBresult, error) {
	/* triggers table search */
	result, err := dbUpdater.DB.Select(
		"select status,state from triggers where triggerid = %s and flags in(%d, %d)",
		triggerId, ZBXLINK_FLAG_DISCOVERY_NORMAL, ZBXLINK_FLAG_DISCOVERY_CREATED,
	)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func DBUpdater(db database.DBConnection) zbxlink.ZabbixUpdater {
	return &Updater{DB: db}
}
