/**
* Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "Common.h"
#include <boost/date_time/gregorian/gregorian.hpp>

int32_t parseDateExpressionToInt(const boost::gregorian::date& date) {
  if (date.is_not_a_date()) {
    throw IoTDBException("Date expression is null or empty.");
  }

  const int year = date.year();
  if (year < 1000 || year > 9999) {
    throw DateTimeParseException("Year must be between 1000 and 9999.",
                                 boost::gregorian::to_iso_extended_string(date), 0);
  }

  const int64_t result = static_cast<int64_t>(year) * 10000 + date.month() * 100 + date.day();
  if (result > INT32_MAX || result < INT32_MIN) {
    throw DateTimeParseException("Date value overflow. ",
                                 boost::gregorian::to_iso_extended_string(date), 0);
  }
  return static_cast<int32_t>(result);
}

boost::gregorian::date parseIntToDate(int32_t dateInt) {
  if (dateInt == EMPTY_DATE_INT) {
    return boost::gregorian::date(boost::date_time::not_a_date_time);
  }
  int year = dateInt / 10000;
  int month = (dateInt % 10000) / 100;
  int day = dateInt % 100;
  return boost::gregorian::date(year, month, day);
}

std::string getTimePrecision(int32_t timeFactor) {
  if (timeFactor >= 1000000)
    return "us";
  if (timeFactor >= 1000)
    return "ms";
  return "s";
}

std::string formatDatetime(const std::string& format, const std::string& precision,
                           int64_t timestamp, const std::string& zoneId) {
  // Simplified implementation - in real code you'd use proper timezone handling
  std::time_t time = static_cast<std::time_t>(timestamp);
  std::tm* tm = std::localtime(&time);
  char buffer[80];
  strftime(buffer, sizeof(buffer), format.c_str(), tm);
  return std::string(buffer);
}

std::tm convertToTimestamp(int64_t value, int32_t timeFactor) {
  std::time_t time = static_cast<std::time_t>(value / timeFactor);
  return *std::localtime(&time);
}

TSDataType::TSDataType getDataTypeByStr(const std::string& typeStr) {
  if (typeStr == "BOOLEAN")
    return TSDataType::BOOLEAN;
  if (typeStr == "INT32")
    return TSDataType::INT32;
  if (typeStr == "INT64")
    return TSDataType::INT64;
  if (typeStr == "FLOAT")
    return TSDataType::FLOAT;
  if (typeStr == "DOUBLE")
    return TSDataType::DOUBLE;
  if (typeStr == "TEXT")
    return TSDataType::TEXT;
  if (typeStr == "TIMESTAMP")
    return TSDataType::TIMESTAMP;
  if (typeStr == "DATE")
    return TSDataType::DATE;
  if (typeStr == "BLOB")
    return TSDataType::BLOB;
  if (typeStr == "STRING")
    return TSDataType::STRING;
  if (typeStr == "OBJECT")
    return TSDataType::OBJECT;
  return TSDataType::UNKNOWN;
}

std::tm int32ToDate(int32_t value) {
  // Convert days since epoch (1970-01-01) to tm struct
  std::time_t time = static_cast<std::time_t>(value) * 86400; // seconds per day
  return *std::localtime(&time);
}

void RpcUtils::verifySuccess(const TSStatus& status) {
  if (status.code == TSStatusCode::MULTIPLE_ERROR) {
    verifySuccess(status.subStatus);
    return;
  }
  if (status.code != TSStatusCode::SUCCESS_STATUS &&
      status.code != TSStatusCode::REDIRECTION_RECOMMEND) {
    throw ExecutionException(to_string(status.code) + ": " + status.message, status);
  }
}

void RpcUtils::verifySuccessWithRedirection(const TSStatus& status) {
  verifySuccess(status);
  if (status.__isset.redirectNode) {
    throw RedirectException(to_string(status.code) + ": " + status.message, status.redirectNode);
  }
  if (status.__isset.subStatus) {
    auto statusSubStatus = status.subStatus;
    vector<TEndPoint> endPointList(statusSubStatus.size());
    int count = 0;
    for (TSStatus subStatus : statusSubStatus) {
      if (subStatus.__isset.redirectNode) {
        endPointList[count++] = subStatus.redirectNode;
      } else {
        TEndPoint endPoint;
        endPointList[count++] = endPoint;
      }
    }
    if (!endPointList.empty()) {
      throw RedirectException(to_string(status.code) + ": " + status.message, endPointList);
    }
  }
}

void RpcUtils::verifySuccessWithRedirectionForMultiDevices(const TSStatus& status,
                                                           vector<string> devices) {
  verifySuccess(status);

  if (status.code == TSStatusCode::MULTIPLE_ERROR ||
      status.code == TSStatusCode::REDIRECTION_RECOMMEND) {
    map<string, TEndPoint> deviceEndPointMap;
    vector<TSStatus> statusSubStatus;
    for (int i = 0; i < statusSubStatus.size(); i++) {
      TSStatus subStatus = statusSubStatus[i];
      if (subStatus.__isset.redirectNode) {
        deviceEndPointMap.insert(make_pair(devices[i], subStatus.redirectNode));
      }
    }
    throw RedirectException(to_string(status.code) + ": " + status.message, deviceEndPointMap);
  }

  if (status.__isset.redirectNode) {
    throw RedirectException(to_string(status.code) + ": " + status.message, status.redirectNode);
  }
  if (status.__isset.subStatus) {
    auto statusSubStatus = status.subStatus;
    vector<TEndPoint> endPointList(statusSubStatus.size());
    int count = 0;
    for (TSStatus subStatus : statusSubStatus) {
      if (subStatus.__isset.redirectNode) {
        endPointList[count++] = subStatus.redirectNode;
      } else {
        TEndPoint endPoint;
        endPointList[count++] = endPoint;
      }
    }
    if (!endPointList.empty()) {
      throw RedirectException(to_string(status.code) + ": " + status.message, endPointList);
    }
  }
}

void RpcUtils::verifySuccess(const vector<TSStatus>& statuses) {
  for (const TSStatus& status : statuses) {
    if (status.code != TSStatusCode::SUCCESS_STATUS) {
      throw BatchExecutionException(status.message, statuses);
    }
  }
}

TSStatus RpcUtils::getStatus(TSStatusCode::TSStatusCode tsStatusCode) {
  TSStatus status;
  status.__set_code(tsStatusCode);
  return status;
}

TSStatus RpcUtils::getStatus(int code, const string& message) {
  TSStatus status;
  status.__set_code(code);
  status.__set_message(message);
  return status;
}

shared_ptr<TSExecuteStatementResp>
RpcUtils::getTSExecuteStatementResp(TSStatusCode::TSStatusCode tsStatusCode) {
  TSStatus status = getStatus(tsStatusCode);
  return getTSExecuteStatementResp(status);
}

shared_ptr<TSExecuteStatementResp>
RpcUtils::getTSExecuteStatementResp(TSStatusCode::TSStatusCode tsStatusCode,
                                    const string& message) {
  TSStatus status = getStatus(tsStatusCode, message);
  return getTSExecuteStatementResp(status);
}

shared_ptr<TSExecuteStatementResp> RpcUtils::getTSExecuteStatementResp(const TSStatus& status) {
  shared_ptr<TSExecuteStatementResp> resp(new TSExecuteStatementResp());
  TSStatus tsStatus(status);
  resp->__set_status(status);
  return resp;
}

shared_ptr<TSFetchResultsResp>
RpcUtils::getTSFetchResultsResp(TSStatusCode::TSStatusCode tsStatusCode) {
  TSStatus status = getStatus(tsStatusCode);
  return getTSFetchResultsResp(status);
}

shared_ptr<TSFetchResultsResp>
RpcUtils::getTSFetchResultsResp(TSStatusCode::TSStatusCode tsStatusCode,
                                const string& appendMessage) {
  TSStatus status = getStatus(tsStatusCode, appendMessage);
  return getTSFetchResultsResp(status);
}

shared_ptr<TSFetchResultsResp> RpcUtils::getTSFetchResultsResp(const TSStatus& status) {
  shared_ptr<TSFetchResultsResp> resp(new TSFetchResultsResp());
  TSStatus tsStatus(status);
  resp->__set_status(tsStatus);
  return resp;
}

MyStringBuffer::MyStringBuffer() : pos(0) {
  checkBigEndian();
}

MyStringBuffer::MyStringBuffer(const std::string& str) : str(str), pos(0) {
  checkBigEndian();
}

void MyStringBuffer::reserve(size_t n) {
  str.reserve(n);
}

void MyStringBuffer::clear() {
  str.clear();
  pos = 0;
}

bool MyStringBuffer::hasRemaining() {
  return pos < str.size();
}

int MyStringBuffer::getInt() {
  return *(int*)getOrderedByte(4);
}

boost::gregorian::date MyStringBuffer::getDate() {
  return parseIntToDate(getInt());
}

int64_t MyStringBuffer::getInt64() {
#ifdef ARCH32
  const char* buf_addr = getOrderedByte(8);
  if (reinterpret_cast<uint32_t>(buf_addr) % 4 == 0) {
    return *(int64_t*)buf_addr;
  } else {
    char tmp_buf[8];
    memcpy(tmp_buf, buf_addr, 8);
    return *(int64_t*)tmp_buf;
  }
#else
  return *(int64_t*)getOrderedByte(8);
#endif
}

float MyStringBuffer::getFloat() {
  return *(float*)getOrderedByte(4);
}

double MyStringBuffer::getDouble() {
#ifdef ARCH32
  const char* buf_addr = getOrderedByte(8);
  if (reinterpret_cast<uint32_t>(buf_addr) % 4 == 0) {
    return *(double*)buf_addr;
  } else {
    char tmp_buf[8];
    memcpy(tmp_buf, buf_addr, 8);
    return *(double*)tmp_buf;
  }
#else
  return *(double*)getOrderedByte(8);
#endif
}

char MyStringBuffer::getChar() {
  if (pos >= str.size()) {
    throw IoTDBException("MyStringBuffer::getChar: read past end (pos=" + std::to_string(pos) +
                         ", size=" + std::to_string(str.size()) + ")");
  }
  return str[pos++];
}

bool MyStringBuffer::getBool() {
  return getChar() == 1;
}

std::string MyStringBuffer::getString() {
  const int lenInt = getInt();
  if (lenInt < 0) {
    throw IoTDBException("MyStringBuffer::getString: negative length");
  }
  const size_t len = static_cast<size_t>(lenInt);
  if (pos > str.size() || len > str.size() - pos) {
    throw IoTDBException(
        "MyStringBuffer::getString: length exceeds buffer (pos=" + std::to_string(pos) +
        ", len=" + std::to_string(len) + ", size=" + std::to_string(str.size()) + ")");
  }
  const size_t tmpPos = pos;
  pos += len;
  return str.substr(tmpPos, len);
}

void MyStringBuffer::putInt(int ins) {
  putOrderedByte((char*)&ins, 4);
}

void MyStringBuffer::putDate(boost::gregorian::date date) {
  putInt(parseDateExpressionToInt(date));
}

void MyStringBuffer::putInt64(int64_t ins) {
  putOrderedByte((char*)&ins, 8);
}

void MyStringBuffer::putFloat(float ins) {
  putOrderedByte((char*)&ins, 4);
}

void MyStringBuffer::putDouble(double ins) {
  putOrderedByte((char*)&ins, 8);
}

void MyStringBuffer::putChar(char ins) {
  str += ins;
}

void MyStringBuffer::putBool(bool ins) {
  char tmp = ins ? 1 : 0;
  str += tmp;
}

void MyStringBuffer::putString(const std::string& ins) {
  putInt((int)(ins.size()));
  str += ins;
}

void MyStringBuffer::concat(const std::string& ins) {
  str.append(ins);
}

void MyStringBuffer::checkBigEndian() {
  static int chk = 0x0201; //used to distinguish CPU's type (BigEndian or LittleEndian)
  isBigEndian = (0x01 != *(char*)(&chk));
}

const char* MyStringBuffer::getOrderedByte(size_t len) {
  if (pos > str.size() || len > str.size() - pos) {
    throw IoTDBException(
        "MyStringBuffer::getOrderedByte: read past end (pos=" + std::to_string(pos) +
        ", len=" + std::to_string(len) + ", size=" + std::to_string(str.size()) + ")");
  }
  const char* p = nullptr;
  if (isBigEndian) {
    p = str.c_str() + pos;
  } else {
    const char* tmp = str.c_str();
    for (size_t i = pos; i < pos + len; i++) {
      numericBuf[pos + len - 1 - i] = tmp[i];
    }
    p = numericBuf;
  }
  pos += len;
  return p;
}

void MyStringBuffer::putOrderedByte(char* buf, int len) {
  if (isBigEndian) {
    str.assign(buf, len);
  } else {
    for (int i = len - 1; i > -1; i--) {
      str += buf[i];
    }
  }
}

BitMap::BitMap(size_t size) {
  resize(size);
}

void BitMap::resize(size_t size) {
  this->size = size;
  this->bits.resize((size >> 3) + 1); // equal to "size/8 + 1"
  reset();
}

bool BitMap::mark(size_t position) {
  if (position >= size)
    return false;

  bits[position >> 3] |= (char)1 << (position % 8);
  return true;
}

bool BitMap::unmark(size_t position) {
  if (position >= size)
    return false;

  bits[position >> 3] &= ~((char)1 << (position % 8));
  return true;
}

void BitMap::markAll() {
  std::fill(bits.begin(), bits.end(), (char)0XFF);
}

void BitMap::reset() {
  std::fill(bits.begin(), bits.end(), (char)0);
}

bool BitMap::isMarked(size_t position) const {
  if (position >= size)
    return false;

  return (bits[position >> 3] & ((char)1 << (position % 8))) != 0;
}

bool BitMap::isAllUnmarked() const {
  size_t j;
  for (j = 0; j < size >> 3; j++) {
    if (bits[j] != (char)0) {
      return false;
    }
  }
  for (j = 0; j < size % 8; j++) {
    if ((bits[size >> 3] & ((char)1 << j)) != 0) {
      return false;
    }
  }
  return true;
}

bool BitMap::isAllMarked() const {
  size_t j;
  for (j = 0; j < size >> 3; j++) {
    if (bits[j] != (char)0XFF) {
      return false;
    }
  }
  for (j = 0; j < size % 8; j++) {
    if ((bits[size >> 3] & ((char)1 << j)) == 0) {
      return false;
    }
  }
  return true;
}

const std::vector<char>& BitMap::getByteArray() const {
  return this->bits;
}

size_t BitMap::getSize() const {
  return this->size;
}

const std::string UrlUtils::PORT_SEPARATOR = ":";
const std::string UrlUtils::ABB_COLON = "[";

TEndPoint UrlUtils::parseTEndPointIpv4AndIpv6Url(const std::string& endPointUrl) {
  TEndPoint endPoint;

  // Return default TEndPoint if input is empty
  if (endPointUrl.empty()) {
    return endPoint;
  }

  size_t portSeparatorPos = endPointUrl.find_last_of(PORT_SEPARATOR);

  // If no port separator found, treat entire string as IP
  if (portSeparatorPos == std::string::npos) {
    endPoint.__set_ip(endPointUrl);
    return endPoint;
  }

  // Extract port part
  std::string portStr = endPointUrl.substr(portSeparatorPos + 1);

  // Extract IP part
  std::string ip = endPointUrl.substr(0, portSeparatorPos);

  // Handle IPv6 addresses with brackets
  if (ip.find(ABB_COLON) != std::string::npos) {
    // Remove surrounding square brackets for IPv6
    if (ip.size() >= 2 && ip.front() == '[' && ip.back() == ']') {
      ip = ip.substr(1, ip.size() - 2);
    }
  }

  try {
    int port = std::stoi(portStr);
    endPoint.__set_ip(ip);
    endPoint.__set_port(port);
  } catch (const std::exception& e) {
    endPoint.__set_ip(endPointUrl);
  }

  return endPoint;
}
