package com.iqser.red.service.persistence.service.v1.api.shared.model.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DateFormatPatternErrorMessage;

public class DateTimeFormatterProvider {

    private static final int BASE_YEAR = 1950; // base year for two-digit years


    public static DateTimeFormatter createFormatterFromInput(String dateFormats, List<DateFormatPatternErrorMessage> validationErrors) {

        DateTimeFormatterBuilder builder = buildFormatter(dateFormats, validationErrors);
        return builder.toFormatter().withResolverStyle(ResolverStyle.SMART).withLocale(Locale.UK);
    }


    public static DateTimeFormatter createFormatterFromResource(String resourcePath, List<DateFormatPatternErrorMessage> validationErrors) {

        StringBuilder dateFormats = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(DateTimeFormatterProvider.class.getResourceAsStream(resourcePath))))) {
            String line;
            while ((line = reader.readLine()) != null) {
                dateFormats.append(line).append(System.lineSeparator());
            }
        } catch (IOException e) {
            throw new RuntimeException("Error reading date format file: " + e.getMessage(), e);
        }

        return createFormatterFromInput(dateFormats.toString(), validationErrors);
    }


    private static DateTimeFormatterBuilder buildFormatter(String dateFormats, List<DateFormatPatternErrorMessage> errors) {

        DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
        builder.parseCaseInsensitive();

        String[] lines = dateFormats.split("\\r?\\n");
        int lineNumber = 0;
        for (String line : lines) {
            lineNumber++;
            String pattern = line.trim();
            if (!pattern.isEmpty()) {
                try {
                    if (hasTwoDigitsForYear(pattern)) {
                        builder.appendOptional(setBaseYear(pattern));
                    } else {
                        builder.appendOptional(DateTimeFormatter.ofPattern(pattern, Locale.UK));
                    }
                } catch (RuntimeException e) {
                    DateFormatPatternErrorMessage error = DateFormatPatternErrorMessage.builder().line(lineNumber).pattern(pattern).message(e.getMessage()).build();
                    errors.add(error);
                }
            }
        }
        return builder;
    }


    private static boolean hasTwoDigitsForYear(String input) {

        Pattern pattern = Pattern.compile("^[^y]*(y[^y]*){2}$");
        Matcher matcher = pattern.matcher(input);
        return matcher.matches();
    }


    private static DateTimeFormatter setBaseYear(String pattern) {

        DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
        if (pattern.startsWith("yy")) {
            String editedPattern = pattern.substring(2);
            builder.appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, BASE_YEAR).appendPattern(editedPattern);
        } else if (pattern.endsWith("yy")) {
            String editedPattern = pattern.substring(0, pattern.length() - 2);
            builder.appendPattern(editedPattern).appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, BASE_YEAR);
        } else {
            throw new RuntimeException("Date format not supported: " + pattern);
        }
        return builder.toFormatter();
    }

}
