import pandas as pd
import shutil
import os
import io

from ms_mint.Mint import Mint

from pathlib import Path as P

from ms_mint.io import (
    ms_file_to_df,
    mzml_to_pandas_df_pyteomics,
    convert_ms_file_to_feather,
    convert_ms_file_to_parquet,
    MZMLB_AVAILABLE,
)

from paths import (
    TEST_MZML,
    TEST_MZXML,
    TEST_PARQUET,
    TEST_MZMLB_POS,
    TEST_MZML_POS,
    TEST_MZML_NEG,
)


def test__ms_file_to_df__mzML():
    result = ms_file_to_df(TEST_MZML)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns


def test__ms_file_to_df__mzML_timeunit_minutes():
    result = ms_file_to_df(TEST_MZML, time_unit="minutes")
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns


def test__ms_file_to_df__mzXML():
    result = ms_file_to_df(TEST_MZXML)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns


def test__mzml_to_pandas_df_pyteomics_pos():
    result = mzml_to_pandas_df_pyteomics(TEST_MZML_POS)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns
    assert all(result.polarity == "+"), f'Polarity should be "+"\n{result}'


def test__mzml_to_pandas_df_pyteomics_neg():
    result = mzml_to_pandas_df_pyteomics(TEST_MZML_NEG)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns
    assert all(result.polarity == "-"), f'Polarity should be "-"\n{result}'


def test__read_parquet():
    result = ms_file_to_df(TEST_PARQUET)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns


def test__write_read_hdf(tmpdir):
    df = ms_file_to_df(TEST_PARQUET)
    fn = P(tmpdir) / "file.hdf"
    df.to_hdf(fn, key="data")
    result = ms_file_to_df(fn)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns


def test__read_mzMLb(tmpdir):
    if not MZMLB_AVAILABLE:
        return None
    result = ms_file_to_df(TEST_MZMLB_POS)
    expected_cols = [
        "scan_id",
        "ms_level",
        "polarity",
        "scan_time_min",
        "mz",
        "intensity",
    ]
    assert isinstance(result, pd.DataFrame), f"{type(result)} is not a dataframe"
    assert expected_cols == result.columns.to_list(), result.columns
    # assert all(result.polarity == '+'), f'Polarity should be "+"\n{result}'


def test__convert_ms_file_to_feather(tmpdir):
    print(tmpdir)
    shutil.copy(TEST_MZML, tmpdir)
    fn = P(tmpdir) / P(TEST_MZML).name
    fn_out = fn.with_suffix(".feather")
    print(fn, fn_out)
    convert_ms_file_to_feather(fn)
    assert fn_out.is_file(), f"File not generated {fn_out}"
    df = ms_file_to_df(fn)
    df_fea = ms_file_to_df(fn_out)
    assert df_fea.equals(df), "DataFrames not equal"


def test__convert_ms_file_to_parquet(tmpdir):
    print(tmpdir)
    shutil.copy(TEST_MZML, tmpdir)
    fn = P(tmpdir) / P(TEST_MZML).name
    fn_out = fn.with_suffix(".parquet")
    print(fn, fn_out)
    convert_ms_file_to_parquet(fn)
    assert fn_out.is_file(), f"File not generated {fn_out}"
    df = ms_file_to_df(fn)
    df_fea = ms_file_to_df(fn_out)
    assert df_fea.equals(df), "DataFrames not equal"


def test__export_to_excel(tmp_path):
    filename = os.path.join(tmp_path, "output.xlsx")
    mint = Mint(verbose=True)
    mint.ms_files = "tests/data/test.mzXML"
    mint.run()
    mint.export(filename)
    assert os.path.isfile(filename)


def test__export_to_excel_without_fn():
    mint = Mint(verbose=True)
    mint.ms_files = TEST_MZXML
    mint.targets = pd.DataFrame(
        {
            "peak_label": ["A"],
            "mz_mean": [200],
            "mz_width": [10],
            "intensity_threshold": [0],
            "rt_min": [0],
            "rt_max": [10],
            "targets_filename": ["unknown"],
        }
    )
    mint.run()
    buffer = mint.export()
    assert isinstance(buffer, io.BytesIO)
    df = pd.read_excel(buffer, sheet_name="Results")
    assert len(df) == 1, len(df)
    assert df.loc[0, "peak_label"] == "A", df.loc[0, "peak_label"]
    assert df.loc[0, "ms_file"] == P(TEST_MZXML).name, df.loc[0, "ms_file"]

[((29, 13, 29, 37), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(29, 27, 29, 36): 'TEST_MZML'}, {}), '(TEST_MZML)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((43, 13, 43, 58), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (), '', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((57, 13, 57, 38), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(57, 27, 57, 37): 'TEST_MZXML'}, {}), '(TEST_MZXML)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((71, 13, 71, 55), 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', ({(71, 41, 71, 54): 'TEST_MZML_POS'}, {}), '(TEST_MZML_POS)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((86, 13, 86, 55), 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', ({(86, 41, 86, 54): 'TEST_MZML_NEG'}, {}), '(TEST_MZML_NEG)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((101, 13, 101, 40), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(101, 27, 101, 39): 'TEST_PARQUET'}, {}), '(TEST_PARQUET)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((115, 9, 115, 36), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(115, 23, 115, 35): 'TEST_PARQUET'}, {}), '(TEST_PARQUET)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((118, 13, 118, 30), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(118, 27, 118, 29): 'fn'}, {}), '(fn)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((134, 13, 134, 42), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(134, 27, 134, 41): 'TEST_MZMLB_POS'}, {}), '(TEST_MZMLB_POS)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((150, 4, 150, 34), 'shutil.copy', 'shutil.copy', ({(150, 16, 150, 25): 'TEST_MZML', (150, 27, 150, 33): 'tmpdir'}, {}), '(TEST_MZML, tmpdir)', False, 'import shutil\n'), ((154, 4, 154, 34), 'ms_mint.io.convert_ms_file_to_feather', 'convert_ms_file_to_feather', ({(154, 31, 154, 33): 'fn'}, {}), '(fn)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((156, 9, 156, 26), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(156, 23, 156, 25): 'fn'}, {}), '(fn)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((157, 13, 157, 34), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(157, 27, 157, 33): 'fn_out'}, {}), '(fn_out)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((163, 4, 163, 34), 'shutil.copy', 'shutil.copy', ({(163, 16, 163, 25): 'TEST_MZML', (163, 27, 163, 33): 'tmpdir'}, {}), '(TEST_MZML, tmpdir)', False, 'import shutil\n'), ((167, 4, 167, 34), 'ms_mint.io.convert_ms_file_to_parquet', 'convert_ms_file_to_parquet', ({(167, 31, 167, 33): 'fn'}, {}), '(fn)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((169, 9, 169, 26), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(169, 23, 169, 25): 'fn'}, {}), '(fn)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((170, 13, 170, 34), 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', ({(170, 27, 170, 33): 'fn_out'}, {}), '(fn_out)', False, 'from ms_mint.io import ms_file_to_df, mzml_to_pandas_df_pyteomics, convert_ms_file_to_feather, convert_ms_file_to_parquet, MZMLB_AVAILABLE\n'), ((175, 15, 175, 52), 'os.path.join', 'os.path.join', ({(175, 28, 175, 36): 'tmp_path', (175, 38, 175, 51): '"""output.xlsx"""'}, {}), "(tmp_path, 'output.xlsx')", False, 'import os\n'), ((176, 11, 176, 29), 'ms_mint.Mint.Mint', 'Mint', (), '', False, 'from ms_mint.Mint import Mint\n'), ((180, 11, 180, 35), 'os.path.isfile', 'os.path.isfile', ({(180, 26, 180, 34): 'filename'}, {}), '(filename)', False, 'import os\n'), ((184, 11, 184, 29), 'ms_mint.Mint.Mint', 'Mint', (), '', False, 'from ms_mint.Mint import Mint\n'), ((186, 19, 196, 5), 'pandas.DataFrame', 'pd.DataFrame', ({(187, 8, 195, 9): "{'peak_label': ['A'], 'mz_mean': [200], 'mz_width': [10],\n    'intensity_threshold': [0], 'rt_min': [0], 'rt_max': [10],\n    'targets_filename': ['unknown']}"}, {}), "({'peak_label': ['A'], 'mz_mean': [200], 'mz_width': [10],\n    'intensity_threshold': [0], 'rt_min': [0], 'rt_max': [10],\n    'targets_filename': ['unknown']})", True, 'import pandas as pd\n'), ((200, 9, 200, 52), 'pandas.read_excel', 'pd.read_excel', (), '', True, 'import pandas as pd\n'), ((116, 9, 116, 18), 'pathlib.Path', 'P', ({(116, 11, 116, 17): 'tmpdir'}, {}), '(tmpdir)', True, 'from pathlib import Path as P\n'), ((151, 9, 151, 18), 'pathlib.Path', 'P', ({(151, 11, 151, 17): 'tmpdir'}, {}), '(tmpdir)', True, 'from pathlib import Path as P\n'), ((164, 9, 164, 18), 'pathlib.Path', 'P', ({(164, 11, 164, 17): 'tmpdir'}, {}), '(tmpdir)', True, 'from pathlib import Path as P\n'), ((151, 21, 151, 33), 'pathlib.Path', 'P', ({(151, 23, 151, 32): 'TEST_MZML'}, {}), '(TEST_MZML)', True, 'from pathlib import Path as P\n'), ((164, 21, 164, 33), 'pathlib.Path', 'P', ({(164, 23, 164, 32): 'TEST_MZML'}, {}), '(TEST_MZML)', True, 'from pathlib import Path as P\n'), ((203, 35, 203, 48), 'pathlib.Path', 'P', ({(203, 37, 203, 47): 'TEST_MZXML'}, {}), '(TEST_MZXML)', True, 'from pathlib import Path as P\n')]