from datetime import date, datetime
from unittest import TestCase

from vbv_lernwelt.importer.utils import (
    parse_circle_group_string,
    try_parse_date,
    try_parse_datetime,
    try_parse_int,
)


class TryParseDateTestCase(TestCase):
    def test_wrongData_returnsFalseAndValue(self):
        flag, value = try_parse_date("nonsense")

        self.assertFalse(flag)
        self.assertEqual("nonsense", value)

    def test_isoDate_returnsCorrectDate(self):
        flag, value = try_parse_date("2015-01-20")

        self.assertTrue(flag)
        self.assertEqual(date(2015, 1, 20), value)

    def test_isoDateWithTime_returnsCorrectDate(self):
        flag, value = try_parse_date("2015-01-20T15:21")

        self.assertTrue(flag)
        self.assertEqual(date(2015, 1, 20), value)

    def test_isoDateWithTime2_returnsCorrectDate(self):
        flag, value = try_parse_date("2018-05-03T00:00:00")

        self.assertTrue(flag)
        self.assertEqual(date(2018, 5, 3), value)

    def test_swissDate_returnsCorrectDate(self):
        flag, value = try_parse_date("01.05.2018")

        self.assertTrue(flag)
        self.assertEqual(date(2018, 5, 1), value)

    def test_wrongIsoDate_returnsFalseAndValue(self):
        flag, value = try_parse_date("2015-14-40")

        self.assertFalse(flag)
        self.assertEqual("2015-14-40", value)

    def test_inputIsDate_returnsDate(self):
        flag, value = try_parse_date(date(2016, 5, 1))

        self.assertTrue(flag)
        self.assertEqual(date(2016, 5, 1), value)

    def test_inputIsNumber_returnsFalseAndNumber(self):
        flag, value = try_parse_date(123)

        self.assertFalse(flag)
        self.assertEqual(123, value)

    def test_inputIsNumberString_returnsFalseAndString(self):
        flag, value = try_parse_date("56")

        self.assertFalse(flag)
        self.assertEqual("56", value)

    def test_inputIsFloatString_returnsFalseAndString(self):
        flag, value = try_parse_date("3.14")

        self.assertFalse(flag)
        self.assertEqual("3.14", value)

    def test_inputIsShortDateWithoutYear_returnsFalseAndString(self):
        flag, value = try_parse_date("11-01")

        self.assertFalse(flag)
        self.assertEqual("11-01", value)


class TryParseInt(TestCase):
    def test_int_works(self):
        flag, value = try_parse_int(123)

        self.assertTrue(flag)
        self.assertEqual(123, value)

    def test_valid_string_works(self):
        flag, value = try_parse_int("123")

        self.assertTrue(flag)
        self.assertEqual(123, value)

    def test_invalid_string_breaks(self):
        flag, value = try_parse_int("123qwer")

        self.assertFalse(flag)
        self.assertEqual("123qwer", value)

    def test_invalid_string_returns_default(self):
        flag, value = try_parse_int("123qwer", 0)

        self.assertFalse(flag)
        self.assertEqual(0, value)


class TryParseDateTimeTestCase(TestCase):
    def test_isoDateTime_returnsCorrectDateTime(self):
        flag, value = try_parse_datetime("2016-05-31T10:00:00.000000")

        self.assertTrue(flag)
        self.assertEqual(datetime(2016, 5, 31, 10, 0, 0), value)

    def test_isoDateTimeWithoutSeconds_returnsCorrectDateTime(self):
        flag, value = try_parse_datetime("2016-05-02T10:00")

        self.assertTrue(flag)
        self.assertEqual(datetime(2016, 5, 2, 10, 0, 0), value)

    def test_isoDateWithoutTime_returnTrueAndDatetimeWithZeroHour(self):
        flag, value = try_parse_datetime("2016-05-31")

        self.assertTrue(flag)
        self.assertEqual(datetime(2016, 5, 31), value)

    def test_isoDateWithSpaceBeforeTime_returnTrueAndDatetimeWithZeroHour(self):
        flag, value = try_parse_datetime("2016-05-03 14:12")

        self.assertTrue(flag)
        self.assertEqual(datetime(2016, 5, 3, 14, 12), value)

    def test_swissDateWithTime_returnTrueAndDatetime(self):
        flag, value = try_parse_datetime("01.05.2018 15:20")

        self.assertTrue(flag)
        self.assertEqual(datetime(2018, 5, 1, 15, 20), value)

    def test_swissDateWithTimeWithMultipleSpaces_returnTrueAndDatetime(self):
        flag, value = try_parse_datetime("01 .05. 2018    15:20")

        self.assertTrue(flag)
        self.assertEqual(datetime(2018, 5, 1, 15, 20), value)

    def test_withDateTimeInput_returnsTrueAndDateTime(self):
        flag, value = try_parse_datetime(datetime(2016, 5, 31, 10, 0))

        self.assertTrue(flag)
        self.assertEqual(datetime(2016, 5, 31, 10, 0, 0), value)

    def test_inputIsNumber_returnsFalseAndNumber(self):
        flag, value = try_parse_datetime(123)

        self.assertFalse(flag)
        self.assertEqual(123, value)

    def test_inputIsNumberString_returnsFalseAndString(self):
        flag, value = try_parse_datetime("56")

        self.assertFalse(flag)
        self.assertEqual("56", value)

    def test_inputIsFloatString_returnsFalseAndString(self):
        flag, value = try_parse_datetime("3.14")

        self.assertFalse(flag)
        self.assertEqual("3.14", value)

    def test_inputIsShortDateWithoutYear_returnsFalseAndString(self):
        flag, value = try_parse_date("11-01")

        self.assertFalse(flag)
        self.assertEqual("11-01", value)

    def test_inputIsTimeString_returnsCurrentDateWithGivenTime(self):
        flag, value = try_parse_datetime(" 15:00")

        self.assertFalse(flag)
        self.assertEqual(" 15:00", value)

    def test_inputFromVbvExcel_returnsCurrentDateWithGivenTime(self):
        flag, value = try_parse_datetime("09.06.2023, 13:30")

        self.assertTrue(flag)
        self.assertEqual(datetime(2023, 6, 9, 13, 30, 0), value)


class ParseCircleGroupStringTestCase(TestCase):
    def test_withMultipleCircles(self):
        value = "Fahrzeug (A, B), Reisen (A), KMU (B)"
        self.assertEqual(
            ["Fahrzeug (A, B)", "Reisen (A)", "KMU (B)"],
            parse_circle_group_string(value),
        )
