/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "mocks/hci_core.h"
#include "mocks/hci_core_expects.h"
#include "mocks/settings.h"
#include "mocks/settings_expects.h"
#include "mocks/smp.h"
#include "testing_common_defs.h"

#include <zephyr/bluetooth/hci.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>

#include <host/hci_core.h>
#include <host/id.h>

/* Hold data representing HCI command response for command BT_HCI_OP_READ_BD_ADDR */
static struct net_buf hci_cmd_rsp;

/* Hold data representing response data for HCI command BT_HCI_OP_READ_BD_ADDR */
static struct bt_hci_rp_read_bd_addr hci_rp_read_bd_addr;

static void tc_setup(void *f)
{
	Z_TEST_SKIP_IFNDEF(CONFIG_BT_SETTINGS);

	memset(&bt_dev, 0x00, sizeof(struct bt_dev));
	memset(&hci_cmd_rsp, 0x00, sizeof(struct net_buf));
	memset(&hci_rp_read_bd_addr, 0x00, sizeof(struct bt_hci_rp_read_bd_addr));

	HCI_CORE_FFF_FAKES_LIST(RESET_FAKE);
	SETTINGS_FFF_FAKES_LIST(RESET_FAKE);

	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
		SMP_FFF_FAKES_LIST(RESET_FAKE);
	}
}

ZTEST_SUITE(bt_setup_public_id_addr_bt_settings_enabled, NULL, NULL, tc_setup, NULL, NULL);

/*
 *  Test reading controller public address fails and no attempt to store settings.
 *
 *  Constraints:
 *   - bt_id_read_public_addr() returns zero
 *
 *  Expected behaviour:
 *   - ID count is set to 0 and bt_setup_public_id_addr() returns 0
 *   - No expected calls to bt_settings_store_id()
 */
ZTEST(bt_setup_public_id_addr_bt_settings_enabled, test_bt_id_read_public_addr_returns_zero)
{
	int err;

	/* This will force bt_id_read_public_addr() to fail */
	bt_hci_cmd_send_sync_fake.return_val = 1;

	err = bt_setup_public_id_addr();

	expect_not_called_bt_settings_store_id();

	zassert_true(bt_dev.id_count == 0, "Incorrect value '%d' was set to bt_dev.id_count",
		     bt_dev.id_count);
	zassert_true(err == 0, "Unexpected error code '%d' was returned", err);
}

static int bt_hci_cmd_send_sync_custom_fake(uint16_t opcode, struct net_buf *buf,
					    struct net_buf **rsp)
{
	const char *func_name = "bt_hci_cmd_send_sync";

	zassert_equal(opcode, BT_HCI_OP_READ_BD_ADDR, "'%s()' was called with incorrect '%s' value",
		      func_name, "opcode");
	zassert_is_null(buf, "'%s()' was called with incorrect '%s' value", func_name, "buf");
	zassert_not_null(rsp, "'%s()' was called with incorrect '%s' value", func_name, "rsp");

	*rsp = &hci_cmd_rsp;
	hci_cmd_rsp.data = (void *)&hci_rp_read_bd_addr;

	return 0;
}

/*
 *  Test reading controller public address through bt_hci_cmd_send_sync().
 *  Even if the operation succeeded, bt_settings_store_id() shouldn't be called to
 *  store settings as the 'BT_DEV_READY' bit isn't set.
 *
 *  Constraints:
 *   - bt_hci_cmd_send_sync() returns zero
 *   - Response data contains a valid address
 *   - BT_DEV_READY bit isn't set in bt_dev.flags
 *
 *  Expected behaviour:
 *   - Return value is 0
 *   - Public address is loaded to bt_dev.id_addr[]
 *   - No expected calls to bt_settings_save_id()
 */
ZTEST(bt_setup_public_id_addr_bt_settings_enabled,
	  test_bt_id_read_public_addr_succeeds_bt_dev_ready_cleared)
{
	int err;
	struct bt_hci_rp_read_bd_addr *rp = (void *)&hci_rp_read_bd_addr;

	bt_addr_copy(&rp->bdaddr, BT_ADDR);
	bt_hci_cmd_send_sync_fake.custom_fake = bt_hci_cmd_send_sync_custom_fake;

	atomic_clear_bit(bt_dev.flags, BT_DEV_READY);

	err = bt_setup_public_id_addr();

	expect_not_called_bt_settings_store_id();

	zassert_true(err == 0, "Unexpected error code '%d' was returned", err);
	zassert_mem_equal(&bt_dev.id_addr[BT_ID_DEFAULT], BT_LE_ADDR, sizeof(bt_addr_le_t),
			  "Incorrect address was set");
	zassert_true(bt_dev.id_count == 1, "Incorrect value '%d' was set to bt_dev.id_count",
		     bt_dev.id_count);
}

/*
 *  Test reading controller public address through bt_hci_cmd_send_sync(). With
 *  the 'BT_DEV_READY' bit set, bt_settings_store_id() should be called to store
 *  settings to persistent memory.
 *
 *  Constraints:
 *   - bt_hci_cmd_send_sync() returns zero
 *   - Response data contains a valid address
 *   - BT_DEV_READY bit isn't set in bt_dev.flags
 *
 *  Expected behaviour:
 *   - Return value is 0
 *   - Public address is loaded to bt_dev.id_addr[]
 *   - No expected calls to bt_settings_save_id()
 */
ZTEST(bt_setup_public_id_addr_bt_settings_enabled,
	  test_bt_id_read_public_addr_succeeds_bt_dev_ready_set)
{
	int err;
	struct bt_hci_rp_read_bd_addr *rp = (void *)&hci_rp_read_bd_addr;

	bt_addr_copy(&rp->bdaddr, BT_ADDR);
	bt_hci_cmd_send_sync_fake.custom_fake = bt_hci_cmd_send_sync_custom_fake;

	atomic_set_bit(bt_dev.flags, BT_DEV_READY);

	err = bt_setup_public_id_addr();

	expect_single_call_bt_settings_store_id();

	zassert_true(err == 0, "Unexpected error code '%d' was returned", err);
	zassert_mem_equal(&bt_dev.id_addr[BT_ID_DEFAULT], BT_LE_ADDR, sizeof(bt_addr_le_t),
			  "Incorrect address was set");
	zassert_true(bt_dev.id_count == 1, "Incorrect value '%d' was set to bt_dev.id_count",
		     bt_dev.id_count);
}

/*
 *  Test reading controller public address through bt_hci_cmd_send_sync().
 *  'BT_DEV_STORE_ID' should be set when IRK isn't set.
 *
 *  Constraints:
 *   - bt_hci_cmd_send_sync() returns zero
 *   - Response data contains a valid address
 *   - CONFIG_BT_PRIVACY is enabled
 *
 *  Expected behaviour:
 *   - Return value is 0
 *   - 'BT_DEV_STORE_ID' bit is set inside bt_dev.flags
 */
ZTEST(bt_setup_public_id_addr_bt_settings_enabled, test_store_flag_set_correctly)
{
	int err;
	struct bt_hci_rp_read_bd_addr *rp = (void *)&hci_rp_read_bd_addr;

	Z_TEST_SKIP_IFNDEF(CONFIG_BT_PRIVACY);

	bt_addr_copy(&rp->bdaddr, BT_ADDR);
	bt_smp_irk_get_fake.return_val = 1;
	bt_hci_cmd_send_sync_fake.custom_fake = bt_hci_cmd_send_sync_custom_fake;

	err = bt_setup_public_id_addr();

	zassert_true(err == 0, "Unexpected error code '%d' was returned", err);
	zassert_true(atomic_test_bit(bt_dev.flags, BT_DEV_STORE_ID),
		     "Flags were not correctly set");
}
