/*
 * 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 <sys/stat.h>
#include <sys/types.h>

#include <cstdio>
#include <set>
#ifdef _WIN32
#include <direct.h>
#define lstat stat
#endif
#include <fstream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include "cli/exit_codes.h"
#include "commands/commands.h"
#include "common/device_id.h"
#include "common/schema.h"
#include "format/atomic_output.h"
#include "format/output_format.h"
#include "reader/tsfile_reader.h"

namespace tsfile_cli {
namespace {

bool stat_is_directory(const struct stat& st) {
#ifdef _WIN32
    return (st.st_mode & S_IFDIR) != 0;
#else
    return S_ISDIR(st.st_mode);
#endif
}

bool directory_exists(const std::string& path) {
    struct stat st;
    return stat(path.c_str(), &st) == 0 && stat_is_directory(st);
}

int make_directory(const std::string& path) {
#ifdef _WIN32
    return _mkdir(path.c_str());
#else
    return mkdir(path.c_str(), 0777);
#endif
}

int create_directory_no_replace(const std::string& path, std::ostream& err) {
    struct stat existing;
    if (lstat(path.c_str(), &existing) == 0) {
        err << "Error: output directory '" << path << "' already exists\n";
        return kExitRuntime;
    }
    if (make_directory(path) != 0) {
        err << "Error: cannot create output directory '" << path << "'\n";
        return kExitRuntime;
    }
    if (!directory_exists(path)) {
        err << "Error: output path '" << path << "' is not a directory\n";
        return kExitRuntime;
    }
    return kExitOk;
}

int write_atomic_text(const std::string& path, const std::string& content,
                      const std::string& source, bool force,
                      std::ostream& err) {
    std::string tmp;
    int code = prepare_atomic_output(path, source, force, tmp, err);
    if (code != kExitOk) {
        return code;
    }
    {
        std::ofstream out(tmp.c_str(), std::ios::binary | std::ios::trunc);
        if (!out.is_open()) {
            err << "Error: cannot create output target '" << path << "'\n";
            remove_atomic_temp(tmp, err);
            return kExitRuntime;
        }
        out << content;
        out.flush();
        if (!out.good()) {
            err << "Error: failed to write output target '" << path << "'\n";
            out.close();
            remove_atomic_temp(tmp, err);
            return kExitRuntime;
        }
        out.close();
        if (out.fail()) {
            err << "Error: failed to close output target '" << path << "'\n";
            remove_atomic_temp(tmp, err);
            return kExitRuntime;
        }
    }
    code = commit_atomic_output(tmp, path, force, err);
    if (code != kExitOk && !remove_atomic_temp(tmp, err)) {
        code = kExitRuntime;
    }
    return code;
}

std::string extension_for_format(ParsedArgs::Format fmt) {
    if (fmt == ParsedArgs::Format::kCsv) {
        return ".csv";
    }
    if (fmt == ParsedArgs::Format::kJson) {
        return ".ndjson";
    }
    return ".txt";
}

std::string type_name_for_format(ParsedArgs::Format fmt) {
    if (fmt == ParsedArgs::Format::kCsv) {
        return "csv";
    }
    if (fmt == ParsedArgs::Format::kJson) {
        return "ndjson";
    }
    return "table";
}

std::string numbered_file_name(size_t index, ParsedArgs::Format fmt) {
    char buf[32];
    std::snprintf(buf, sizeof(buf), "%04zu", index + 1);
    return std::string(buf) + extension_for_format(fmt);
}

struct ManifestEntry {
    std::string file;
    std::string model;
    std::string object;
    std::string type;
    std::string rows;
};

std::string render_manifest(bool complete,
                            const std::vector<ManifestEntry>& entries) {
    std::ostringstream out;
    out << "{\n  \"complete\": " << (complete ? "true" : "false")
        << ",\n  \"files\": [\n";
    for (size_t i = 0; i < entries.size(); ++i) {
        const ManifestEntry& e = entries[i];
        out << "    {\"file\":\"" << json_escape(e.file) << "\",\"model\":\""
            << json_escape(e.model) << "\",\"object\":\""
            << json_escape(e.object) << "\",\"type\":\"" << json_escape(e.type)
            << "\",\"rows\":\"" << json_escape(e.rows) << "\"}";
        if (i + 1 != entries.size()) {
            out << ",";
        }
        out << "\n";
    }
    out << "  ]\n}\n";
    return out.str();
}

int write_manifest(const std::string& dir, bool complete,
                   const std::vector<ManifestEntry>& entries,
                   std::ostream& err) {
    return write_atomic_text(dir + "/_manifest.json",
                             render_manifest(complete, entries), "", true, err);
}

int stream_query_to_file(const ParsedArgs& args, storage::TsFileReader& reader,
                         OutputFormat fmt, const std::string& path, bool force,
                         long long& rows, std::ostream& err) {
    std::string temp;
    int code = prepare_atomic_output(path, args.file, force, temp, err);
    if (code != kExitOk) {
        return code;
    }
    std::ofstream output(temp.c_str(), std::ios::binary | std::ios::trunc);
    if (!output.is_open()) {
        err << "Error: cannot open temporary output for '" << path << "'\n";
        remove_atomic_temp(temp, err);
        return kExitRuntime;
    }
    code = run_row_query(args, reader, fmt, output, err, args.offset,
                         args.limit, &rows);
    output.flush();
    if (code == kExitOk && !output.good()) {
        err << "Error: failed to flush output target '" << path << "'\n";
        code = kExitRuntime;
    }
    output.close();
    if (code == kExitOk && output.fail()) {
        err << "Error: failed to close output target '" << path << "'\n";
        code = kExitRuntime;
    }
    if (code == kExitOk) {
        code = commit_atomic_output(temp, path, force, err);
    }
    if (code != kExitOk && !remove_atomic_temp(temp, err)) {
        code = kExitRuntime;
    }
    return code;
}

bool table_exists(storage::TsFileReader& reader, const std::string& table) {
    const std::string canonical = storage::to_lower(table);
    auto schemas = reader.get_all_table_schemas();
    for (const auto& schema : schemas) {
        if (schema && schema->get_table_name() == canonical) {
            return true;
        }
    }
    return false;
}

bool device_exists(storage::TsFileReader& reader, const std::string& device) {
    auto did = std::make_shared<storage::StringArrayDeviceID>(device);
    std::vector<storage::MeasurementSchema> schema;
    return reader.get_timeseries_schema(did, schema) == 0 && !schema.empty();
}

int validate_multi_export_objects(const ParsedArgs& args,
                                  storage::TsFileReader& reader,
                                  std::ostream& err) {
    std::set<std::string> seen;
    if (!args.tables.empty()) {
        for (const std::string& table : args.tables) {
            const std::string canonical = storage::to_lower(table);
            if (!seen.insert(canonical).second) {
                err << "Error: table '" << table
                    << "' was specified more than once\n";
                return kExitUsage;
            }
            if (!table_exists(reader, table)) {
                err << "Error: table '" << table << "' does not exist\n";
                return kExitUsage;
            }
        }
    } else {
        for (const std::string& device : args.devices) {
            if (!seen.insert(device).second) {
                err << "Error: device '" << device
                    << "' was specified more than once\n";
                return kExitUsage;
            }
            if (!device_exists(reader, device)) {
                err << "Error: device '" << device << "' does not exist\n";
                return kExitUsage;
            }
        }
    }
    OutputNameValidator validator;
    const bool table_mode = !args.tables.empty();
    const std::vector<std::string>& objects =
        table_mode ? args.tables : args.devices;
    for (const std::string& object : objects) {
        const std::string name =
            table_mode ? storage::to_lower(object) : object;
        if (!validator.add_object(name)) {
            err << "Error: " << validator.error() << "\n";
            return kExitFile;
        }
        ParsedArgs scope = args;
        scope.table = table_mode ? name : "";
        scope.device = table_mode ? "" : name;
        const int code = validate_row_query_names(scope, reader, err);
        if (code != kExitOk) return code;
    }
    return kExitOk;
}

}  // namespace

int cmd_export(const ParsedArgs& args, storage::TsFileReader& reader,
               OutputFormat fmt, std::ostream& /*out*/, std::ostream& err) {
    const bool multi_object = args.devices.size() + args.tables.size() > 1;
    if (multi_object) {
        int code = validate_multi_export_objects(args, reader, err);
        if (code != kExitOk) {
            return code;
        }
        code = create_directory_no_replace(args.output_dir, err);
        if (code != kExitOk) {
            return code;
        }

        std::vector<ManifestEntry> entries;
        code = write_manifest(args.output_dir, false, entries, err);
        if (code != kExitOk) {
            return code;
        }

        const std::vector<std::string>& objects =
            !args.tables.empty() ? args.tables : args.devices;
        const bool table_mode = !args.tables.empty();
        for (size_t i = 0; i < objects.size(); ++i) {
            ParsedArgs one = args;
            one.output = args.output_dir + "/" +
                         numbered_file_name(i, args.export_format);
            one.output_dir.clear();
            one.devices.clear();
            one.tables.clear();
            one.device.clear();
            one.table.clear();
            if (table_mode) {
                one.table = storage::to_lower(objects[i]);
                one.tables.push_back(one.table);
            } else {
                one.device = objects[i];
                one.devices.push_back(objects[i]);
            }
            one.command = "cat";
            long long rows = 0;
            code = stream_query_to_file(one, reader, fmt, one.output, false,
                                        rows, err);
            if (code != kExitOk) {
                return code;
            }
            entries.push_back({numbered_file_name(i, args.export_format),
                               table_mode ? "table" : "tree",
                               table_mode ? one.table : objects[i],
                               type_name_for_format(args.export_format),
                               std::to_string(rows)});
            code = write_manifest(args.output_dir, false, entries, err);
            if (code != kExitOk) {
                if (std::remove(one.output.c_str()) != 0) {
                    err << "Error: failed to clean unrecorded output '"
                        << one.output << "'\n";
                    return kExitRuntime;
                }
                return code;
            }
        }
        return write_manifest(args.output_dir, true, entries, err);
    }

    ParsedArgs query = args;
    query.command = "cat";
    const int code = validate_row_query_names(query, reader, err);
    if (code != kExitOk) return code;
    long long rows = 0;
    return stream_query_to_file(query, reader, fmt, args.output, args.force,
                                rows, err);
}

}  // namespace tsfile_cli
