import shutil

from pathlib import Path
from unittest import TestCase
from unittest.mock import Mock
from unittest.mock import patch

from foliant.config.downloadfile import download_file
from foliant.config.downloadfile import get_file_ext_from_url
from foliant.config.downloadfile import get_file_name_from_url


class TestDownloadFile(TestCase):
    def setUp(self):
        self.project_dir = (Path(__file__).parent / 'project_dir').resolve()
        self.project_dir.mkdir(exist_ok=True)

    def tearDown(self):
        shutil.rmtree(self.project_dir, ignore_errors=True)

    @patch('foliant.config.downloadfile.urlopen', autospec=True)
    def test_only_url(self, urlopen):
        mock_response = Mock()
        mock_response.read.return_value = b'File content'
        urlopen.return_value = mock_response

        url = 'http://example.com/myfile.txt'

        download_file(root_dir=self.project_dir, url=url)
        request = urlopen.call_args.args[0]
        context = urlopen.call_args.kwargs['context']

        self.assertEqual(request.headers, {})
        self.assertIsNone(context)

        with open(self.project_dir / 'myfile.txt') as f:
            self.assertEqual(f.read(), 'File content')

    @patch('foliant.config.downloadfile.urlopen', autospec=True)
    def test_save_to(self, urlopen):
        mock_response = Mock()
        mock_response.read.return_value = b'File content'
        urlopen.return_value = mock_response

        url = 'http://example.com/myfile.txt'
        save_to = 'subdir1/subdir2/downloaded.txt'

        download_file(root_dir=self.project_dir, url=url, save_to=save_to)
        request = urlopen.call_args.args[0]
        context = urlopen.call_args.kwargs['context']

        self.assertEqual(request.headers, {})
        self.assertIsNone(context)

        with open(self.project_dir / save_to) as f:
            self.assertEqual(f.read(), 'File content')

    @patch('foliant.config.downloadfile.urlopen', autospec=True)
    def test_with_auth(self, urlopen):
        mock_response = Mock()
        mock_response.read.return_value = b'File content'
        urlopen.return_value = mock_response

        url = 'http://example.com/myfile.txt'

        download_file(
            root_dir=self.project_dir,
            url=url,
            login='john',
            password='qwerty1234'
        )
        request = urlopen.call_args.args[0]
        context = urlopen.call_args.kwargs['context']

        self.assertIn('Authorization', request.headers)
        self.assertIsNone(context)

        with open(self.project_dir / 'myfile.txt') as f:
            self.assertEqual(f.read(), 'File content')


class TestGetFileNameFromURL(TestCase):
    def test_with_ext(self):
        url = 'http://example.com/sub/myfile.txt'
        name = get_file_name_from_url(url)
        self.assertEqual(name, 'myfile.txt')

    def test_no_ext(self):
        url = 'http://example.com/sub/myfile'
        name = get_file_name_from_url(url)
        self.assertEqual(name, 'myfile')

    def test_with_clutter(self):
        url = 'http://example.com/sub/myfile.txt?param=val&foo=bar'
        name = get_file_name_from_url(url)
        self.assertEqual(name, 'myfile.txt')


class TestGetFileExtFromURL(TestCase):
    def test_with_ext(self):
        url = 'http://example.com/sub/myfile.txt'
        ext = get_file_ext_from_url(url)
        self.assertEqual(ext, '.txt')

    def test_no_ext(self):
        url = 'http://example.com/sub/myfile'
        ext = get_file_ext_from_url(url)
        self.assertEqual(ext, '')

    def test_with_clutter(self):
        url = 'http://example.com/sub/myfile.txt?param=val&foo=bar'
        ext = get_file_ext_from_url(url)
        self.assertEqual(ext, '.txt')

[((21, 5, 21, 64), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import patch\n'), ((39, 5, 39, 64), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import patch\n'), ((58, 5, 58, 64), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import patch\n'), ((19, 8, 19, 59), 'shutil.rmtree', 'shutil.rmtree', (), '', False, 'import shutil\n'), ((23, 24, 23, 30), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock\n'), ((29, 8, 29, 57), 'foliant.config.downloadfile.download_file', 'download_file', (), '', False, 'from foliant.config.downloadfile import download_file\n'), ((41, 24, 41, 30), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock\n'), ((48, 8, 48, 74), 'foliant.config.downloadfile.download_file', 'download_file', (), '', False, 'from foliant.config.downloadfile import download_file\n'), ((60, 24, 60, 30), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock\n'), ((66, 8, 71, 9), 'foliant.config.downloadfile.download_file', 'download_file', (), '', False, 'from foliant.config.downloadfile import download_file\n'), ((85, 15, 85, 42), 'foliant.config.downloadfile.get_file_name_from_url', 'get_file_name_from_url', ({(85, 38, 85, 41): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_name_from_url\n'), ((90, 15, 90, 42), 'foliant.config.downloadfile.get_file_name_from_url', 'get_file_name_from_url', ({(90, 38, 90, 41): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_name_from_url\n'), ((95, 15, 95, 42), 'foliant.config.downloadfile.get_file_name_from_url', 'get_file_name_from_url', ({(95, 38, 95, 41): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_name_from_url\n'), ((102, 14, 102, 40), 'foliant.config.downloadfile.get_file_ext_from_url', 'get_file_ext_from_url', ({(102, 36, 102, 39): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_ext_from_url\n'), ((107, 14, 107, 40), 'foliant.config.downloadfile.get_file_ext_from_url', 'get_file_ext_from_url', ({(107, 36, 107, 39): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_ext_from_url\n'), ((112, 14, 112, 40), 'foliant.config.downloadfile.get_file_ext_from_url', 'get_file_ext_from_url', ({(112, 36, 112, 39): 'url'}, {}), '(url)', False, 'from foliant.config.downloadfile import get_file_ext_from_url\n'), ((15, 28, 15, 42), 'pathlib.Path', 'Path', ({(15, 33, 15, 41): '__file__'}, {}), '(__file__)', False, 'from pathlib import Path\n')]