package cz.moneta.test.dsl.util;

import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Date;
import java.util.Random;

public final class TestUtils {

    private TestUtils() {
    }

    public static String getEmailBasedOnRc(String rc) {
        return rc + "@moneta.cz";
    }

    public static Date getTodayAsDate() {
        return new Date(LocalDate.now().toEpochDay());
    }

    /**
     * Get today date in dd.MM.yyyy format. If you want to get today date in different format, use {@link #getTodayDate(String)}
     *
     * @return today date in format dd.MM.yyyy
     */
    public static String getTodayDate() {
        return TestUtils.getTodayDate("dd.MM.yyyy");
    }

    /**
     * @param pattern {@link java.time.format.DateTimeFormatter}
     * @return today date in specified format
     */
    public static String getTodayDate(String pattern) {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    public static Date dateFromString(String date, String format) {
        try {
            return new SimpleDateFormat(format).parse(date);
        } catch (ParseException e) {
            throw new IllegalStateException("Error during date parsing: " + e.getMessage());
        }
    }

    public static String parseBirthDateAsString(String birthNumber) {
        LocalDate dateOfBirth = parseBirthDate(birthNumber);
        if (dateOfBirth == null) return null;
        return dateOfBirth.format(DateTimeFormatter.ofPattern("d.M.yyyy"));
    }

    public static LocalDate parseBirthDate(String birthNumber) {
        if (birthNumber == null || birthNumber.length() < 6) {
            return null;
        }

        int year = Integer.parseInt(birthNumber.substring(0, 2));
        int month = Integer.parseInt(birthNumber.substring(2, 4));
        int day = Integer.parseInt(birthNumber.substring(4, 6));

        boolean isWoman = month > 50;
        if (isWoman) {
            month -= 50;
        }

        boolean isModifiedMonth = month > 20;
        if (isModifiedMonth) {
            month -= 20;
        }

        boolean isECP = day > 40;
        if (isECP) {
            day -= 40;
        }

        year = correctYear(birthNumber, year);

        return LocalDate.of(year, month, day);
    }


    static int correctYear(String birthNumber, int year) {
        if (birthNumber.length() == 9) {
            if (year > 53) {
                year += 1800;
            } else {
                year += 1900;
            }
        } else {
            if (year > 53) {
                year += 1900;
            } else {
                year += 2000;
            }
        }
        return year;
    }

    public static BigDecimal toNumber(String number) {
        return new BigDecimal(number.replace("Kč", "")
                .replace(",-", "")
                .replace(",", ".")
                .replaceAll("\\s", ""));
    }

    public static BigDecimal toPercentWithTwoDecimals(BigDecimal value) {
        value = value.multiply(new BigDecimal(100));
        return value.setScale(2, RoundingMode.HALF_EVEN);
    }

    public static String encodeBase64(String textToEncode) {
        return Base64.getUrlEncoder()
                .encodeToString(textToEncode.getBytes());
    }

    public static String toStringWithTwoDecimals(int value) {
        DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance();
        DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
        symbols.setGroupingSeparator(' ');
        formatter.setDecimalFormatSymbols(symbols);
        return formatter.format(value) + ",00";
    }

    public static String toString(int value) {
        return String.valueOf(value);
    }

    public static String getContentFromResource(String relativePath) {
        String result = "";
        try (InputStream inputStream = TestUtils.class.getClassLoader().getResourceAsStream(relativePath)) {
            result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getB64FromResource(String relativePath) {
        String result = "data:image/jpeg;base64,";
        try (InputStream inputStream = TestUtils.class.getClassLoader().getResourceAsStream(relativePath)) {
            result += IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static <T extends Enum<?>> T getRandomValueFromEnum(Class<T> aClass) {
        Random random = new Random();
        int x = random.nextInt(aClass.getEnumConstants().length);
        return aClass.getEnumConstants()[x];
    }

}
