#include "tlbmc/sensors/hwmon_temp_sensor.h"

#include <algorithm>
#include <array>
#include <charconv>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT: system_error is commonly used in BMC
#include <utility>
#include <vector>

#include "google/protobuf/duration.pb.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "boost/asio.hpp"  // NOLINT: boost::asio is commonly used in BMC
#include "boost/asio/random_access_file.hpp"  // NOLINT: boost::asio is commonly used in BMC
#include "boost/filesystem.hpp"  // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/filesystem/operations.hpp"  // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/system/detail/error_code.hpp"  // NOLINT: boost::asio is commonly used in BMC
#include "g3/macros.h"
// NOLINTNEXTLINE: keep this so BUILD file will keep liburing
#include "liburing.h"  // IWYU pragma: keep
#include "tlbmc/central_config/config.h"
#include "entity_common_config.pb.h"
#include "hal_common_config.pb.h"
#include "hwmon_temp_sensor_config.pb.h"
#include "reading_range_config.pb.h"
#include "threshold_config.pb.h"
#include "tlbmc/hal/sysfs/hwmon.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "tlbmc/sensors/ixc_hwmon_based_sensor.h"
#include "tlbmc/sensors/sensor.h"
#include "tlbmc/time/time.h"

namespace milotic_tlbmc {

template <class TypeName>
struct TypeComparator {
  // Compared by the first element which is the type name.
  bool operator()(const std::pair<HwmonTempSensorType, TypeName>& lhs,
                  const std::pair<HwmonTempSensorType, TypeName>& rhs) const {
    return lhs.first < rhs.first;
  }
};

constexpr std::array<std::pair<HwmonTempSensorType, std::string_view>, 4>
    kSupportedHwmonTempSensorTypes = {{
        // go/keep-sorted start numeric=yes
        {HWMON_TEMP_SENSOR_TYPE1_MAX31725, "max31725"},
        {HWMON_TEMP_SENSOR_TYPE2_TMP75, "tmp75"},
        {HWMON_TEMP_SENSOR_TYPE3_MAX31732, "max31732"},
        {HWMON_TEMP_SENSOR_TYPE4_SA56004, "sa56004"},
        // go/keep-sorted end
    }};

absl::StatusOr<std::string_view> HwmonTempSensor::GetDriverName(
    HwmonTempSensorType sensor_type) {
  const auto* it = std::lower_bound(
      kSupportedHwmonTempSensorTypes.begin(),
      kSupportedHwmonTempSensorTypes.end(),
      std::pair<HwmonTempSensorType, std::string_view>{sensor_type, ""},
      TypeComparator<std::string_view>());
  if (it == kSupportedHwmonTempSensorTypes.end() || it->first != sensor_type) {
    return absl::InvalidArgumentError(
        absl::Substitute("Unsupported sensor type: $0", sensor_type));
  }
  return it->second;
}

absl::flat_hash_map<std::string, std::string>
HwmonTempSensor::CreateLabelToInputFileMap(
    const boost::filesystem::path& hwmon_path) {
  absl::flat_hash_map<std::string, std::string> label_to_input_file;
  for (const auto& entry : boost::filesystem::directory_iterator(hwmon_path)) {
    constexpr std::string_view kInputFileSuffix = "_input";
    constexpr std::string_view kLabelSuffix = "_label";
    if (entry.is_regular_file() &&
        absl::EndsWith(entry.path().filename().string(), kInputFileSuffix)) {
      // e.g., /sys/bus/i2c/devices/i2c-21/21-0040/hwmon/hwmon15/temp100_input
      std::string input_file = entry.path().filename().string();
      std::string file_prefix =
          input_file.substr(0, input_file.size() - kInputFileSuffix.size());
      std::string label_file = absl::StrCat(file_prefix, kLabelSuffix);
      // Both input file and label file should exist
      boost::filesystem::path label_path = hwmon_path / label_file;
      if (boost::filesystem::exists(label_path)) {
        std::ifstream file(label_path.string());
        std::string label = {std::istreambuf_iterator<char>(file),
                             std::istreambuf_iterator<char>()};
        label = std::string(absl::StripTrailingAsciiWhitespace(label));
        label_to_input_file[label] = input_file;
      } else if (boost::filesystem::exists(hwmon_path / input_file)) {
        // If label file does not exist, use input file name prefix as label.
        label_to_input_file[file_prefix] = input_file;
      }
    }
  }
  return label_to_input_file;
}

std::shared_ptr<HwmonTempSensor> HwmonTempSensor::CreateHwmonTempSensor(
    const std::string& name, const std::string& label,
    const std::string& input_dev_path, const HwmonTempSensorConfig& config,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    std::optional<NotificationCb> on_batch_notify,
    const HwmonSysfs& hwmon_sysfs) {
  std::string hwmon_temp_sensor_key = absl::StrCat("temperature_", name);

  ThresholdConfigs threshold_configs;
  if (auto it = config.label_to_thresholds().find(label);
      it != config.label_to_thresholds().end()) {
    threshold_configs = it->second;
  }

  ReadingRangeConfigs reading_range_configs;
  if (auto it = config.label_to_reading_ranges().find(label);
      it != config.label_to_reading_ranges().end()) {
    reading_range_configs = it->second;
  }

  return std::make_shared<HwmonTempSensor>(
      Token(), config.type(), input_dev_path, label, hwmon_temp_sensor_key,
      config.hal_common_config(), threshold_configs, reading_range_configs,
      config.entity_common_config(), io_context, on_batch_notify, hwmon_sysfs);
}

absl::StatusOr<std::vector<std::shared_ptr<Sensor>>> HwmonTempSensor::Create(
    const HwmonTempSensorConfig& config,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    const HwmonSysfs& hwmon_sysfs,
    std::optional<NotificationCb> on_batch_notify) {
  DLOG(INFO) << "Creating HwmonTempSensor for device: " << absl::StrCat(config);

  const HalCommonConfig& hal_common_config = config.hal_common_config();
  ECCLESIA_ASSIGN_OR_RETURN(std::string_view driver_name,
                            GetDriverName(config.type()));

  std::vector<std::shared_ptr<Sensor>> sensors;

  absl::StatusOr<boost::filesystem::path> hwmon_path =
      IXcHwmonBasedSensor::CreateIXcDeviceAndReturnsHwmonPath(
          hal_common_config, driver_name, hwmon_sysfs);
  if (!hwmon_path.ok()) {
    // Only fail if the sensor is detected and the config is not allowed to
    // fail.
    if (!GetTlbmcConfig()
             .sensor_collector_module()
             .allow_sensor_creation_failure() &&
        config.entity_common_config().config_detected()) {
      return hwmon_path.status();
    }

    LOG(ERROR) << "Failed to create HwmonTempSensor (NONFATAL): "
               << hwmon_path.status();
    for (const auto& [label, name] : config.label_to_name()) {
      std::shared_ptr<HwmonTempSensor> hwmon_temp_sensor =
          CreateHwmonTempSensor(name, label, "", config, io_context,
                                on_batch_notify, hwmon_sysfs);
      State state;
      // If the sensor is not detected, we set its creation as pending otherwise
      // set it to failed.
      if (!config.entity_common_config().config_detected()) {
        state.set_status(STATUS_CREATION_PENDING);
      } else {
        state.set_status(STATUS_CREATION_FAILED);
      }
      state.set_status_message(
          absl::StrCat("Failed to create HwmonTempSensor (NONFATAL): ",
                       hwmon_path.status()));
      hwmon_temp_sensor->UpdateState(std::move(state));
      sensors.push_back(hwmon_temp_sensor);
    }
    return sensors;
  }

  // Now find all labels and their input files.
  absl::flat_hash_map<std::string, std::string> label_to_input_file =
      CreateLabelToInputFileMap(*hwmon_path);

  for (const auto& [label, name] : config.label_to_name()) {
    boost::filesystem::path input_dev_path;

    if (auto it = label_to_input_file.find(label);
        it != label_to_input_file.end()) {
      input_dev_path = *hwmon_path / it->second;
    } else {
      return absl::InvalidArgumentError(absl::Substitute(
          "Failed to find $0 in hwmon folder $1", label, hwmon_path->string()));
    }

    sensors.push_back(
        CreateHwmonTempSensor(name, label, input_dev_path.string(), config,
                              io_context, on_batch_notify, hwmon_sysfs));
  }

  return sensors;
}

absl::Status HwmonTempSensor::ReinitializeInternal() {
  LOG(INFO) << "Reinitializing hwmon temp sensor: " << sensor_name_;

  if (IsInputDeviceUsable()) {
    return absl::FailedPreconditionError(
        absl::StrCat("Attempted to reinitialize usable sensor: ", sensor_name_,
                     ". Ignoring reinitialization."));
  }

  ECCLESIA_ASSIGN_OR_RETURN(std::string_view driver_name,
                            GetDriverName(sensor_type_));

  ECCLESIA_ASSIGN_OR_RETURN(
      boost::filesystem::path hwmon_path,
      IXcHwmonBasedSensor::CreateIXcDeviceAndReturnsHwmonPath(
          sensor_attributes_static_.hal_common_config(), driver_name,
          *hwmon_sysfs_));

  absl::flat_hash_map<std::string, std::string> label_to_input_file =
      CreateLabelToInputFileMap(hwmon_path);

  auto it = label_to_input_file.find(sensor_label_);
  if (it == label_to_input_file.end()) {
    return absl::NotFoundError(
        absl::Substitute("Failed to find $0 in hwmon folder $1", sensor_label_,
                         hwmon_path.string()));
  }

  SetInputDevicePath((hwmon_path / it->second).string());

  // Set to Status UNKNOWN to simulate fresh creation of Sensor object.
  State state;
  state.set_status(STATUS_UNKNOWN);
  UpdateState(std::move(state));

  // Set up the input device file for reading. This must be done last as right
  // after this function is done, the sensor is readable.
  SetUpInput();

  LOG(WARNING) << "Successfully reinitialized hwmon temp sensor: "
               << sensor_name_;

  return absl::OkStatus();
}

void HwmonTempSensor::Reinitialize(
    absl::AnyInvocable<void(absl::Status)> callback) {
  boost::asio::post(*io_context_,
                    [this, callback = std::move(callback)]() mutable {
                      callback(ReinitializeInternal());
                    });
}

void HwmonTempSensor::HandleRefreshResult(
    const boost::system::error_code& error, size_t bytes_read) {
  if (error) {
    State state;
    state.set_status(STATUS_STALE);
    state.set_status_message(absl::Substitute(
        "Failed to read from input device: $0; input device path: $1",
        error.message(), GetInputDevicePath()));
    UpdateState(std::move(state));
    return;
  }
  const char* buffer_end = GetConstReadBuffer().data() + bytes_read;
  int64_t value = 0;
  std::from_chars_result result =
      std::from_chars(GetConstReadBuffer().data(), buffer_end, value);
  if (result.ec != std::errc()) {
    State state;
    state.set_status(STATUS_STALE);
    state.set_status_message(
        absl::StrCat("Read data can't be converted to a number: ",
                     std::make_error_condition(result.ec).message()));
    UpdateState(std::move(state));
    return;
  }
  double scale = sensor_attributes_static_.reading_transform().scale();
  if (GetSensorAttributesStatic().unit() == UNIT_DEGREE_CELSIUS) {
    // Temperatures are read in milli degrees Celsius, we need
    // degrees Celsius.
    // https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
    scale *= 0.001;
  }
  SensorValue sensor_data;
  *sensor_data.mutable_timestamp() = Now();
  sensor_data.set_reading(
      ((static_cast<double>(value) +
        sensor_attributes_static_.reading_transform().offset()) *
       scale));
  StoreSensorData(std::make_shared<const SensorValue>(std::move(sensor_data)));
  State state;
  state.set_status(STATUS_READY);
  UpdateState(std::move(state));
}

HwmonTempSensor::HwmonTempSensor(
    Token token, HwmonTempSensorType sensor_type,
    const std::string& input_dev_path, const std::string& sensor_label,
    const std::string& sensor_name, const HalCommonConfig& hal_common_config,
    const ThresholdConfigs& threshold_configs,
    const ReadingRangeConfigs& reading_range_configs,
    const EntityCommonConfig& entity_common_config,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    std::optional<NotificationCb> on_batch_notify,
    const HwmonSysfs& hwmon_sysfs)
    : IXcHwmonBasedSensor(input_dev_path, io_context,
                          CreateStaticAttributes(
                              sensor_name, UNIT_DEGREE_CELSIUS,
                              hal_common_config, entity_common_config,
                              reading_range_configs, ReadingTransformConfig()),
                          threshold_configs, on_batch_notify, hwmon_sysfs),
      sensor_type_(sensor_type),
      sensor_label_(sensor_label),
      sensor_name_(sensor_name){}

}  // namespace milotic_tlbmc
