/**
* 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;
    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() {
    return str[pos++];
}

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

std::string MyStringBuffer::getString() {
    size_t len = getInt();
    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) {
    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;
}
