#pragma once

/**
 * \file
 * \brief Интерфейсы управления состоянием подсистемы MDB Cashless.
 *
 * Файл содержит:
 * - IStateProvider — интерфейс доступа и изменения текущего состояния,
 * - IStateNotifier — интерфейс сигналов об изменении состояния,
 * - IStateService — объединённый интерфейс (provider + notifier).
 *
 * Интерфейсы используются для централизованного хранения и
 * распространения состояния подсистемы безналичной оплаты,
 * включая:
 * - состояние MDB-сервиса,
 * - текущее состояние автомата (State),
 * - параметры Expansion Enable Options,
 * - активную сессию продажи (VendSession),
 * - результаты продаж (VendResult).
 *
 * IStateProvider отвечает за изменение состояния,
 * IStateNotifier — за уведомление подписчиков через Qt-сигналы.
 *
 * Типы (State, VendSession, VendResult, ExpansionEnableOptions и др.)
 * определены в types.h.
 *
 * При использовании этих типов в Qt и DBus:
 * - регистрация QMetaType выполняется через registerMetaTypes(),
 * - регистрация DBus-мета-типов выполняется через registerDbusMetaTypes().
 */

#include <QObject>

#include "types.h"

namespace aqsi {
namespace mdb {
namespace cashless {

using namespace aqsi::mdb::cashless;

/**
 * \brief Интерфейс поставщика состояния подсистемы MDB Cashless.
 *
 * Определяет контракт для хранения и изменения текущего состояния
 * безналичного устройства и связанного MDB-сервиса.
 *
 * Реализация интерфейса отвечает за:
 * - хранение флага активности MDB-сервиса,
 * - хранение текущего состояния автомата (State),
 * - управление параметрами Expansion Enable Options,
 * - хранение активной сессии продажи (VendSession),
 * - фиксацию результатов продажи (VendResult).
 *
 * Интерфейс используется компонентами-адаптерами и сервисами
 * бизнес-логики для централизованного изменения состояния.
 */
class AQSIMDB_EXPORT IStateProvider
{
public:
    /**
     * \brief Проверяет, активен ли сервисный компонент, отвечающий за связь с автоматом по MDB.
     * \return true, если MDB-сервис активен (работает и готов к обмену); false в противном случае.
     */
    virtual bool isServiceActive() const = 0;
    /**
     * \brief Устанавливает флаг активности MDB-сервиса.
     * \param active true — сервис активен; false — неактивен.
     */
    virtual void setServiceActive(bool const active) = 0;

    /**
     * \brief Возвращает текущие параметры Expansion Enable Options.
     */
    virtual aqsi::mdb::cashless::ExpansionEnableOptions expansionEnableOptions() const = 0;
    /**
     * \brief Устанавливает параметры Expansion Enable Options.
     */
    virtual void setExpansionEnableOptions(aqsi::mdb::cashless::ExpansionEnableOptions const options) = 0;

    /**
     * \brief Возвращает текущую активную сессию продажи.
     * \return Активная сессия либо std::nullopt, если сессии нет.
     */
    virtual std::optional<aqsi::mdb::cashless::VendSession> vendSession() const = 0;

    /**
     * \brief Возвращает текущее состояние автомата.
     */
    virtual State state() const = 0;

    /**
     * \brief Устанавливает новое состояние без изменения контекста сессии.
     */
    virtual void setState(aqsi::mdb::cashless::State const state) = 0;

    /**
     * \brief Устанавливает состояние и связанный контекст сессии атомарно.
     *
     * Используется при переходах состояний, связанных с операциями продажи.
     */
    virtual void setSessionContext(
        aqsi::mdb::cashless::State const state,
        std::optional<aqsi::mdb::cashless::VendSession> const& vend_session) = 0;

    /**
     * \brief Добавляет результат продажи в текущий контекст.
     *
     * \param vend_result Результат операции (успех/ошибка).
     * \param remaining_count Количество оставшихся попыток или операций.
     */
    virtual void addVendResult(aqsi::mdb::cashless::VendResult const& vend_result, uint8_t const remaining_count) = 0;
};

/**
 * \brief Интерфейс уведомления об изменениях состояния подсистемы MDB Cashless.
 *
 * Предоставляет набор Qt-сигналов, транслирующих изменения состояния, происходящие в IStateProvider.
 *
 * Используется для:
 * - оповещения UI-компонентов,
 * - синхронизации внешних сервисов,
 * - проброса событий в DBus-слой.
 */
class AQSIMDB_EXPORT IStateNotifier : public QObject
{
    Q_OBJECT

public:
    using QObject::QObject;

signals:
    void serviceActiveChanged(bool const active);

    void expansionEnableOptionsChanged(aqsi::mdb::cashless::ExpansionEnableOptions const options);

    void stateChanged(aqsi::mdb::cashless::State const state);

    void sessionContextReplaced(
        aqsi::mdb::cashless::State const state, std::optional<aqsi::mdb::cashless::VendSession> const& session_info);

    void vendResultAdded(aqsi::mdb::cashless::VendResult const& vend_result, uint8_t const remaining_count);
};

class AQSIMDB_EXPORT IStateService : public IStateNotifier, public IStateProvider
{
    Q_OBJECT

public:
    using IStateNotifier::IStateNotifier;
};
}  // namespace cashless
}  // namespace mdb
}  // namespace aqsi
