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, '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'), (43, '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, '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'), (71, 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', 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, 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', 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, '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'), (115, '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'), (118, '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'), (134, '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'), (150, 'shutil.copy', 'shutil.copy', False, 'import shutil\n'), (154, 'ms_mint.io.convert_ms_file_to_feather', 'convert_ms_file_to_feather', 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, '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'), (157, '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'), (163, 'shutil.copy', 'shutil.copy', False, 'import shutil\n'), (167, 'ms_mint.io.convert_ms_file_to_parquet', 'convert_ms_file_to_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'), (169, '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'), (170, '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'), (175, 'os.path.join', 'os.path.join', False, 'import os\n'), (176, 'ms_mint.Mint.Mint', 'Mint', False, 'from ms_mint.Mint import Mint\n'), (180, 'os.path.isfile', 'os.path.isfile', False, 'import os\n'), (184, 'ms_mint.Mint.Mint', 'Mint', False, 'from ms_mint.Mint import Mint\n'), (186, 'pandas.DataFrame', 'pd.DataFrame', True, 'import pandas as pd\n'), (200, 'pandas.read_excel', 'pd.read_excel', True, 'import pandas as pd\n'), (116, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n'), (151, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n'), (164, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n'), (151, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n'), (164, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n'), (203, 'pathlib.Path', 'P', True, 'from pathlib import Path as P\n')]