import pytest

from utils.fasta_handling import get_sequences_from_fasta


class TestFastaParsing:
    def run_test(self, acc_set, lst_of_fasta_strings, mocker):
        mocker.patch('builtins.open', mocker.mock_open(read_data=lst_of_fasta_strings[0]))
        mocker.patch('utils.search_result_parsing.helper_classes.InputFile.encoding',
                     new_callable=mocker.PropertyMock, return_value='utf8')
        return get_sequences_from_fasta(acc_set, ["non_existant_file"])

    def test_single_acc_from_fasta(self, mocker):
        fasta_str = """\
>tr|A0A126QUZ5|A0A126QUZ5_9EURY Uncharacterized
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
PYFVT
"""
        accs = {"A0A126QUZ5"}
        dct_seqs = self.run_test(accs, [fasta_str], mocker)
        assert "A0A126QUZ5" in dct_seqs
        assert dct_seqs["A0A126QUZ5"] == {"MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVTPYFVT"}

    def test_fail_if_acc_only_in_desc(self, mocker):
        fasta_str = """\
>tr|A0A126QUZ5I|A0A126QUZ5_9EURY A0A126QUZ5 A0A126QUZ5 Uncharacterized A0A126QUZ5
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
PYFVT
"""
        accs = {"A0A126QUZ5"}
        dct_seqs = self.run_test(accs, [fasta_str], mocker)
        assert "A0A126QUZ5" not in dct_seqs

    def test_soh_entry(self, mocker):
        fasta_str = """\
>XP_963622.1 1,3-beta-glucanosyltransferase Gel2 [Neurospora crassa OR74A]CAD21216.1 probable beta (1-3) glucanosyltransferase [Neurospora crassa]EAA34386.1 1,3-beta-glucanosyltransferase Gel2 [Neurospora crassa OR74A]KHE87655.1 putative beta (1-3) glucanosyltransferase [Neurospora crassa]
MLIQSTLIALSATLAAAVKPLTVKNQFFVDPNDNIFQIVGVAYQPGGSAGYNAALGKDPLSDGDICRRDAAILQILGVNT
IRVYNLNPD
"""
        accs = {"CAD21216.1"}
        dct_seqs = self.run_test(accs, [fasta_str], mocker)
        assert "CAD21216.1" in dct_seqs

    def test_soh_entry_2(self, mocker):
        fasta_str = """\
>XP_963622.1 1,3-beta-glucanosyltransferase Gel2 [Neurospora crassa OR74A]CAD21216.1EAA34386.1 1,3-beta-glucanosyltransferase Gel2 [Neurospora crassa OR74A]KHE87655.1 putative beta (1-3) glucanosyltransferase [Neurospora crassa]
MLIQSTLIALSATLAAAVKPLTVKNQFFVDPNDNIFQIVGVAYQPGGSAGYNAALGKDPLSDGDICRRDAAILQILGVNT
IRVYNLNPD
"""
        accs = {"CAD21216.1"}
        dct_seqs = self.run_test(accs, [fasta_str], mocker)
        assert "CAD21216.1" in dct_seqs

    @pytest.mark.xfail(reason="test for issue 78: accession found if searched alone but not if provided with others, "
                              "see https://gitlab.com/s.fuchs/prophane/-/issues/78")
    def test_accession_with_pipe(self, mocker):
        acc1 = "A0A126QUZ5"
        acc2 = "tr|9_EURY"
        fasta_str = f"""\
>tr|{acc1}|A0A126QUZ5_9EURY Uncharacterized
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
PYFVT
>{acc2}|DEF Uncharacterized
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
PYFVT
"""
        accs = {acc1, acc2}
        dct_seq = self.run_test(accs, [fasta_str], mocker)
        assert acc1 in dct_seq

    def test_diverse_accessions(self, mocker):
        fasta_str = f"""\
>tr|A0A126QUZ5|A0A126QUZ5_9EURY Uncharacterized
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
>tr|9_EURY|DEF Uncharacterized
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
>XP_963622.1 1,3-beta-glucanosyltransferase Gel2 [Neurospora crassa OR74A]
>9_EURY
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
>NODE_4011_length_2764_cov_62.965992_5
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
>CAD21216.1EAA34386.1
MIFVGDHFKEDGDWIWTSFCATEKYLLGIVADGRGKAVCERIVNTELDKLRRNHMPYFVT
"""
        accs = {"A0A126QUZ5", "9_EURY", "XP_963622.1", "NODE_4011_length_2764_cov_62.965992_5", "CAD21216.1",
                "EAA34386.1"}
        dct_seq = self.run_test(accs, [fasta_str], mocker)
        assert accs == set(dct_seq.keys())
