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', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['TEST_MZML'], {'time_unit': '"""minutes"""'}), 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', (['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, 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', (['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, 'ms_mint.io.mzml_to_pandas_df_pyteomics', 'mzml_to_pandas_df_pyteomics', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'shutil.copy', 'shutil.copy', (['TEST_MZML', 'tmpdir'], {}), False, 'import shutil\n'), (154, 'ms_mint.io.convert_ms_file_to_feather', 'convert_ms_file_to_feather', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'shutil.copy', 'shutil.copy', (['TEST_MZML', 'tmpdir'], {}), False, 'import shutil\n'), (167, 'ms_mint.io.convert_ms_file_to_parquet', 'convert_ms_file_to_parquet', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'ms_mint.io.ms_file_to_df', 'ms_file_to_df', (['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, 'os.path.join', 'os.path.join', (['tmp_path', '"""output.xlsx"""'], {}), False, 'import os\n'), (176, 'ms_mint.Mint.Mint', 'Mint', ([], {'verbose': '(True)'}), False, 'from ms_mint.Mint import Mint\n'), (180, 'os.path.isfile', 'os.path.isfile', (['filename'], {}), False, 'import os\n'), (184, 'ms_mint.Mint.Mint', 'Mint', ([], {'verbose': '(True)'}), False, 'from ms_mint.Mint import Mint\n'), (186, 'pandas.DataFrame', 'pd.DataFrame', (["{'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, 'pandas.read_excel', 'pd.read_excel', (['buffer'], {'sheet_name': '"""Results"""'}), True, 'import pandas as pd\n'), (116, 'pathlib.Path', 'P', (['tmpdir'], {}), True, 'from pathlib import Path as P\n'), (151, 'pathlib.Path', 'P', (['tmpdir'], {}), True, 'from pathlib import Path as P\n'), (164, 'pathlib.Path', 'P', (['tmpdir'], {}), True, 'from pathlib import Path as P\n'), (151, 'pathlib.Path', 'P', (['TEST_MZML'], {}), True, 'from pathlib import Path as P\n'), (164, 'pathlib.Path', 'P', (['TEST_MZML'], {}), True, 'from pathlib import Path as P\n'), (203, 'pathlib.Path', 'P', (['TEST_MZXML'], {}), True, 'from pathlib import Path as P\n')]