/*
 * 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 <fcntl.h>

#include <algorithm>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "cli/cli_args.h"
#include "cli/exit_codes.h"
#include "commands/commands.h"
#include "common/datatype/date_converter.h"
#include "common/schema.h"
#include "common/tablet.h"
#include "file/write_file.h"
#include "format/input_format.h"
#include "writer/tsfile_table_writer.h"

namespace tsfile_cli {
namespace {

struct DataRow {
    long long line_no;
    int64_t timestamp;
    std::vector<std::string> cells;
};

// Parse a calendar date in strict YYYY-MM-DD form into a std::tm (year offset
// from 1900, month 0-based) the way storage::Tablet expects for DATE columns.
// Validates that it is a real date (DateConverter rejects e.g. 2024-13-40),
// since the writer silently drops an invalid std::tm rather than erroring.
bool parse_date_cell(const std::string& cell, std::tm& out) {
    int y = 0;
    int m = 0;
    int d = 0;
    char extra = 0;
    if (std::sscanf(cell.c_str(), "%4d-%2d-%2d%c", &y, &m, &d, &extra) != 3) {
        return false;
    }
    out = std::tm();
    out.tm_year = y - 1900;
    out.tm_mon = m - 1;
    out.tm_mday = d;
    int32_t date_int = 0;
    return common::DateConverter::date_to_int(out, date_int) == common::E_OK;
}

bool add_typed_value(storage::Tablet& tablet, uint32_t row,
                     uint32_t schema_index, const ColumnDef& def,
                     const std::string& cell, std::string& error) {
    if (cell.empty()) {
        return true;  // null
    }
    char* e = nullptr;
    switch (def.type) {
        case common::BOOLEAN: {
            bool v = false;
            if (!parse_bool_cell(cell, v)) {
                error = "bad BOOLEAN '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, v);
            return true;
        }
        case common::INT32: {
            errno = 0;
            long long v = std::strtoll(cell.c_str(), &e, 10);
            if (e == nullptr || *e != '\0') {
                error = "bad INT32 '" + cell + "'";
                return false;
            }
            if (errno == ERANGE || v < INT32_MIN || v > INT32_MAX) {
                error = "INT32 out of range '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, static_cast<int32_t>(v));
            return true;
        }
        case common::INT64: {
            errno = 0;
            long long v = std::strtoll(cell.c_str(), &e, 10);
            if (e == nullptr || *e != '\0') {
                error = "bad INT64 '" + cell + "'";
                return false;
            }
            if (errno == ERANGE) {
                error = "INT64 out of range '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, static_cast<int64_t>(v));
            return true;
        }
        case common::TIMESTAMP: {
            errno = 0;
            long long v = std::strtoll(cell.c_str(), &e, 10);
            if (e == nullptr || *e != '\0') {
                error = "bad TIMESTAMP '" + cell + "'";
                return false;
            }
            if (errno == ERANGE) {
                error = "TIMESTAMP out of range '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, static_cast<int64_t>(v));
            return true;
        }
        case common::DATE: {
            std::tm d;
            if (!parse_date_cell(cell, d)) {
                error = "bad DATE '" + cell + "' (want YYYY-MM-DD)";
                return false;
            }
            tablet.add_value(row, schema_index, d);
            return true;
        }
        case common::FLOAT: {
            errno = 0;
            float v = std::strtof(cell.c_str(), &e);
            if (e == nullptr || *e != '\0') {
                error = "bad FLOAT '" + cell + "'";
                return false;
            }
            if (errno == ERANGE) {
                error = "FLOAT out of range '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, v);
            return true;
        }
        case common::DOUBLE: {
            errno = 0;
            double v = std::strtod(cell.c_str(), &e);
            if (e == nullptr || *e != '\0') {
                error = "bad DOUBLE '" + cell + "'";
                return false;
            }
            if (errno == ERANGE) {
                error = "DOUBLE out of range '" + cell + "'";
                return false;
            }
            tablet.add_value(row, schema_index, v);
            return true;
        }
        case common::STRING:
        case common::TEXT:
        case common::BLOB: {
            // Add by index using the c-string overload to avoid the per-cell
            // name lowercasing + map lookup the by-name overload would do.
            tablet.add_value(row, schema_index, cell.c_str());
            return true;
        }
        default:
            error = "unsupported column type";
            return false;
    }
}

}  // namespace

int cmd_write(const ParsedArgs& args, std::ostream& /*out*/,
              std::ostream& err) {
    std::vector<ColumnDef> columns;
    std::string perr;
    if (!parse_columns_spec(args.columns, columns, perr)) {
        err << "Error: " << perr << "\n";
        return kExitUsage;
    }

    std::istream* in = &std::cin;
    std::ifstream fin;
    if (!args.file.empty() && args.file != "-") {
        fin.open(args.file.c_str());
        if (!fin.is_open()) {
            err << "Error: cannot open input: " << args.file << "\n";
            return kExitFile;
        }
        in = &fin;
    }

    const char delim = (args.format == ParsedArgs::Format::kTsv) ? '\t' : ',';
    const bool csv_quotes = (delim == ',');

    if (args.verbose) {
        // Echo the resolved write configuration so the user can self-check the
        // parsed flags before any rows are imported.
        err << "write: table=" << args.table << " output=" << args.output
            << " input=" << (args.file.empty() ? "-" : args.file)
            << " format=" << (delim == '\t' ? "tsv" : "csv")
            << " header=" << (args.no_header ? "none" : "yes")
            << (args.header_match ? " (match)" : "") << "\n";
        for (const ColumnDef& d : columns) {
            err << "  column " << d.name << ":" << tsdatatype_name(d.type) << ":"
                << (d.category == common::ColumnCategory::TAG ? "tag" : "field")
                << "\n";
        }
    }

    std::string line;
    long long line_no = 0;
    long long record_lines = 0;
    if (!args.no_header) {
        if (read_record(*in, csv_quotes, line, record_lines)) {
            line_no += record_lines;
            if (args.header_match) {
                std::vector<std::string> h =
                    split_line(line, delim, csv_quotes);
                const size_t expected = columns.size() + 1;
                if (h.size() != expected) {
                    err << "Error: header has " << h.size()
                        << " columns, expected " << expected
                        << " (time + --columns) (line 1)\n";
                    return kExitRuntime;
                }
                for (size_t i = 0; i < columns.size(); ++i) {
                    if (h[i + 1] != columns[i].name) {
                        err << "Error: header column " << (i + 2) << " is '"
                            << h[i + 1] << "', expected '" << columns[i].name
                            << "' (line 1)\n";
                        return kExitRuntime;
                    }
                }
            }
        }
    }

    std::vector<std::string> names;
    std::vector<common::TSDataType> types;
    std::vector<common::ColumnCategory> cats;
    std::vector<common::ColumnSchema> col_schemas;
    std::vector<size_t> tag_idx;
    for (size_t j = 0; j < columns.size(); ++j) {
        const ColumnDef& d = columns[j];
        names.push_back(d.name);
        types.push_back(d.type);
        cats.push_back(d.category);
        col_schemas.push_back(common::ColumnSchema(
            d.name, d.type, common::get_default_compressor(),
            common::get_value_encoder(d.type), d.category));
        if (d.category == common::ColumnCategory::TAG) {
            tag_idx.push_back(j);
        }
    }

    // Creating the output truncates it; refuse to clobber the input we are
    // still reading from, which would otherwise silently destroy the source
    // data.
    if (!args.file.empty() && args.file != "-" && args.output == args.file) {
        err << "Error: --output is the same as the input file: " << args.output
            << "\n";
        return kExitUsage;
    }

    storage::WriteFile file;
    int flags = O_WRONLY | O_CREAT | O_TRUNC;
#ifdef _WIN32
    flags |= O_BINARY;
#endif
    int cret = file.create(args.output, flags, 0666);
    if (cret != 0) {
        err << "Error: cannot create output " << args.output << ": "
            << error_code_message(cret) << " (code " << cret << ")\n";
        return kExitFile;
    }
    auto* schema = new storage::TableSchema(args.table, col_schemas);
    auto* writer = new storage::TsFileTableWriter(&file, schema);

    // Stream rows into fixed-size batches so memory stays bounded regardless of
    // input size; a full file is never buffered in memory.
    const size_t kBatch = 1024;
    int result_code = kExitOk;
    long long total_rows = 0;
    std::vector<DataRow> batch;
    batch.reserve(kBatch);
    // The table writer requires strictly increasing timestamps per device, and
    // a device is identified by its tag-column values. Track the last timestamp
    // seen for each device so out-of-order input is rejected with a clear,
    // located message instead of an opaque write failure.
    std::unordered_map<std::string, int64_t> last_ts_by_device;

    auto flush_batch = [&]() -> bool {
        if (batch.empty()) {
            return true;
        }
        storage::Tablet tablet(args.table, names, types, cats,
                               static_cast<int>(batch.size()));
        for (size_t i = 0; i < batch.size(); ++i) {
            uint32_t r = static_cast<uint32_t>(i);
            tablet.add_timestamp(r, batch[i].timestamp);
            for (size_t j = 0; j < columns.size(); ++j) {
                std::string cell_err;
                if (!add_typed_value(tablet, r, static_cast<uint32_t>(j),
                                     columns[j], batch[i].cells[j], cell_err)) {
                    err << "Error: " << cell_err << " (line "
                        << batch[i].line_no << ")\n";
                    return false;
                }
            }
        }
        int wt = writer->write_table(tablet);
        if (wt != 0) {
            err << "Error: failed to write rows: " << error_code_message(wt)
                << " (code " << wt << ")\n";
            return false;
        }
        total_rows += static_cast<long long>(batch.size());
        batch.clear();
        return true;
    };

    while (read_record(*in, csv_quotes, line, record_lines)) {
        line_no += record_lines;
        if (line.empty()) {
            continue;
        }
        std::vector<std::string> fields = split_line(line, delim, csv_quotes);
        if (fields.size() != columns.size() + 1) {
            err << "Error: expected " << (columns.size() + 1) << " fields, got "
                << fields.size() << " (line " << line_no << ")\n";
            result_code = kExitRuntime;
            break;
        }
        char* e = nullptr;
        errno = 0;
        long long ts = std::strtoll(fields[0].c_str(), &e, 10);
        if (e == nullptr || *e != '\0' || errno == ERANGE) {
            err << "Error: bad timestamp '" << fields[0] << "' (line "
                << line_no << ")\n";
            result_code = kExitRuntime;
            break;
        }
        DataRow r;
        r.line_no = line_no;
        r.timestamp = static_cast<int64_t>(ts);
        r.cells.assign(fields.begin() + 1, fields.end());

        std::string device_key;
        for (size_t k : tag_idx) {
            device_key += r.cells[k];
            device_key.push_back('\0');
        }
        auto seen = last_ts_by_device.find(device_key);
        if (seen != last_ts_by_device.end() && r.timestamp <= seen->second) {
            err << "Error: timestamps must be strictly increasing per device "
                   "(line "
                << line_no << ": " << r.timestamp << " <= previous "
                << seen->second << ")\n";
            result_code = kExitRuntime;
            break;
        }
        last_ts_by_device[device_key] = r.timestamp;

        batch.push_back(std::move(r));
        if (batch.size() >= kBatch && !flush_batch()) {
            result_code = kExitRuntime;
            break;
        }
    }

    if (result_code == kExitOk && !flush_batch()) {
        result_code = kExitRuntime;
    }

    if (result_code == kExitOk) {
        int fr = writer->flush();
        if (fr != 0) {
            err << "Error: failed to flush output: " << error_code_message(fr)
                << " (code " << fr << ")\n";
            result_code = kExitRuntime;
        } else {
            int cr = writer->close();
            if (cr != 0) {
                err << "Error: failed to close output: "
                    << error_code_message(cr) << " (code " << cr << ")\n";
                result_code = kExitRuntime;
            }
        }
    } else {
        writer->close();
    }
    delete writer;
    delete schema;

    if (result_code != kExitOk) {
        // The import failed; do not leave a partial/corrupt .tsfile behind.
        file.close();
        std::remove(args.output.c_str());
    } else if (args.verbose) {
        err << "wrote " << total_rows << " rows to " << args.output << "\n";
    }
    return result_code;
}

}  // namespace tsfile_cli
