from __future__ import annotations

import unittest
from pathlib import Path

from doc2md.converter import csv_to_markdown, docx_to_markdown, pdf_to_markdown


ROOT = Path(__file__).resolve().parents[1]
FIX_IN = ROOT / 'tests' / 'fixtures' / 'in'
FIX_OUT = ROOT / 'tests' / 'fixtures' / 'out'

CSV_FIXTURES = [
    ("sample.csv", "sample.csv.md"),
    ("edge.csv", "edge.csv.md"),
]

DOCX_FIXTURES = [
    ("sample.docx", "sample.docx.md"),
    ("edge.docx", "edge.docx.md"),
]

PDF_FIXTURES = [
    ("sample.pdf", "sample.pdf.md"),
    ("edge.pdf", "edge.pdf.md"),
    ("lowtext.pdf", "lowtext.pdf.md"),
]


def read_text(path: Path) -> str:
    return path.read_text(encoding='utf-8')


def assert_normalized(test_case: unittest.TestCase, content: str) -> None:
    test_case.assertNotIn('\r', content)
    lines = content.split('\n')
    if content:
        test_case.assertTrue(content.endswith('\n'))
    for line in lines:
        test_case.assertEqual(line, line.rstrip())

    blank_run = 0
    for line in lines:
        if line == '':
            blank_run += 1
            test_case.assertLessEqual(blank_run, 2)
        else:
            blank_run = 0


class ConverterFixturesTest(unittest.TestCase):
    def test_csv_fixtures(self) -> None:
        for input_name, output_name in CSV_FIXTURES:
            with self.subTest(fixture=input_name):
                expected = read_text(FIX_OUT / output_name)
                actual = csv_to_markdown(FIX_IN / input_name)
                self.assertEqual(actual, expected)
                self.assertTrue(actual.strip())
                assert_normalized(self, actual)

    def test_docx_fixtures(self) -> None:
        for input_name, output_name in DOCX_FIXTURES:
            with self.subTest(fixture=input_name):
                expected = read_text(FIX_OUT / output_name)
                actual = docx_to_markdown(FIX_IN / input_name)
                self.assertEqual(actual, expected)
                self.assertTrue(actual.strip())
                assert_normalized(self, actual)

    def test_pdf_fixtures(self) -> None:
        for input_name, output_name in PDF_FIXTURES:
            with self.subTest(fixture=input_name):
                expected = read_text(FIX_OUT / output_name)
                actual = pdf_to_markdown(FIX_IN / input_name)
                self.assertEqual(actual, expected)
                self.assertTrue(actual.strip())
                assert_normalized(self, actual)


if __name__ == '__main__':
    unittest.main()
