# 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.

import pytest

from tsfile import Field, RowRecord, Tablet, TimeseriesSchema, TSDataType
from tsfile import TsFileReader, TsFileWriter
from tsfile.exceptions import (
    AlreadyExistsError,
    ErrorCode,
    FileOpenError,
    InvalidArgumentError,
    InvalidPathError,
    LibraryError,
    TsFileCorruptedError,
    get_exception,
)


def test_get_exception_preserves_known_and_unknown_codes():
    corrupted = get_exception(ErrorCode.TSFILE_CORRUPTED)
    assert isinstance(corrupted, TsFileCorruptedError)
    assert corrupted.code == ErrorCode.TSFILE_CORRUPTED
    assert corrupted.message == "TsFile is corrupted"

    unknown = get_exception(999, "opening reader")
    assert type(unknown) is LibraryError
    assert unknown.code == 999
    assert unknown.message == "opening reader: Unknown library error"

    retired_codes = {
        *range(9, 20),
        23,
        25,
        39,
        41,
        42,
        46,
        47,
    }
    assert retired_codes.isdisjoint(error.value for error in ErrorCode)
    for code in retired_codes:
        retired = get_exception(code)
        assert type(retired) is LibraryError
        assert retired.code == code
        assert retired.message == "Unknown library error"

    invalid_path = get_exception(37)
    assert isinstance(invalid_path, InvalidPathError)
    assert invalid_path.code == ErrorCode.INVALID_PATH


def test_invalid_tree_path_propagates_native_error(tmp_path):
    path = tmp_path / "invalid-path.tsfile"
    with TsFileWriter(str(path)) as writer:
        writer.register_timeseries(
            "root.device", TimeseriesSchema("value", TSDataType.INT64)
        )

    with TsFileReader(str(path)) as reader:
        with pytest.raises(InvalidPathError) as exc_info:
            reader.query_timeseries("root.device", ["a*%"], 0, 2)

    assert exc_info.value.code == ErrorCode.INVALID_PATH


def test_writer_constructor_propagates_native_error(tmp_path, capsys):
    path = tmp_path / "already-exists.tsfile"
    path.touch()

    with pytest.raises(AlreadyExistsError) as exc_info:
        TsFileWriter(str(path))

    assert exc_info.value.code == ErrorCode.ALREADY_EXIST
    assert exc_info.value.message == "Resource already exists"
    assert capsys.readouterr().out == ""


def test_reader_constructor_propagates_native_errors(tmp_path):
    missing = tmp_path / "missing.tsfile"
    with pytest.raises(FileOpenError) as exc_info:
        TsFileReader(str(missing))
    assert exc_info.value.code == ErrorCode.FILE_OPEN_ERROR

    corrupted = tmp_path / "corrupted.tsfile"
    corrupted.touch()
    with pytest.raises(TsFileCorruptedError) as exc_info:
        TsFileReader(str(corrupted))
    assert exc_info.value.code == ErrorCode.TSFILE_CORRUPTED


def test_duplicate_tablet_columns_do_not_silently_drop_rows(tmp_path):
    path = tmp_path / "duplicate-columns.tsfile"
    with TsFileWriter(str(path)) as writer:
        writer.register_timeseries(
            "root.device", TimeseriesSchema("value", TSDataType.INT64)
        )
        tablet = Tablet(
            ["value", "VALUE"],
            [TSDataType.INT64, TSDataType.INT64],
            max_row_num=1,
        )
        tablet.set_table_name("root.device")
        tablet.add_timestamp(0, 1)
        tablet.add_value_by_index(0, 0, 10)
        tablet.add_value_by_index(1, 0, 20)

        with pytest.raises(InvalidArgumentError) as exc_info:
            writer.write_tablet(tablet)

        assert exc_info.value.code == ErrorCode.INVALID_ARGUMENT
        assert "unique" in exc_info.value.message


def test_row_record_still_writes_after_error_handling_changes(tmp_path):
    path = tmp_path / "row-record.tsfile"
    with TsFileWriter(str(path)) as writer:
        writer.register_timeseries(
            "root.device", TimeseriesSchema("value", TSDataType.INT64)
        )
        writer.write_row_record(
            RowRecord("root.device", 1, [Field("value", 10, TSDataType.INT64)])
        )

    with TsFileReader(str(path)) as reader:
        with reader.query_timeseries("root.device", ["value"], 0, 2) as result:
            assert result.next()
            assert result.get_value_by_index(2) == 10
