/**
* 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>
#include <stdexcept>

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() {
    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;
}

TEndPoint UrlUtils::parseTEndPointIpv4AndIpv6Url(const std::string& endPointUrl) {
    TEndPoint endPoint;
    const size_t colonPos = endPointUrl.find_last_of(':');
    if (colonPos == std::string::npos) {
        endPoint.__set_ip(endPointUrl);
        endPoint.__set_port(0);
        return endPoint;
    }
    std::string ip = endPointUrl.substr(0, colonPos);
    const std::string portStr = endPointUrl.substr(colonPos + 1);
    try {
        const int port = std::stoi(portStr);
        endPoint.__set_port(port);
    } catch (const std::logic_error&) {
        endPoint.__set_ip(endPointUrl);
        endPoint.__set_port(0);
        return endPoint;
    }
    if (ip.size() >= 2 && ip.front() == '[' && ip.back() == ']') {
        ip = ip.substr(1, ip.size() - 2);
    }
    endPoint.__set_ip(ip);
    return endPoint;
}
