package de.avatic.lcc.service.bulk.helper;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class CellStyleProvider {

    public CellStyle createHeaderCellStyle(Workbook workbook) {

        XSSFFont headerFont = (XSSFFont) workbook.createFont();

        headerFont.setColor(PredefinedColors.NEUTRAL.getColor());
        headerFont.setFontName("Arial");
        headerFont.setFontHeightInPoints((short) 11);
        headerFont.setBold(true);

        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFont(headerFont);
        headerStyle.setFillForegroundColor(PredefinedColors.TITLE.getColor());

        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return updateBorderStyle(headerStyle, IndexedColors.WHITE);
    }

    private XSSFFont createFontStyle(Workbook workbook, boolean bold) {
        XSSFFont font = (XSSFFont) workbook.createFont();

        font.setColor(PredefinedColors.TITLE.getColor());
        font.setFontName("Arial");
        font.setFontHeightInPoints((short) 11);
        font.setBold(bold);

        return font;
    }

    private CellStyle updateBorderStyle(CellStyle style, IndexedColors color) {

        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        style.setLeftBorderColor(color.getIndex());
        style.setRightBorderColor(color.getIndex());
        style.setBottomBorderColor(color.getIndex());
        style.setTopBorderColor(color.getIndex());

        return style;
    }


    private CellStyle createStyle(Workbook workbook, Short textFormat, XSSFFont fontStyle) {
        CellStyle style = workbook.createCellStyle();

        style.setFont(fontStyle);
        style.setAlignment(HorizontalAlignment.RIGHT);
        style.setDataFormat(textFormat);

        return updateBorderStyle(style, IndexedColors.GREY_25_PERCENT);
    }


    private CellStyle updateHighlight(CellStyle style, PredefinedColors background) {
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillForegroundColor(background.getColor());
        return style;
    }

    public Map<TextFormat, Map<PredefinedColors, CellStyle>> createCellStyles(Workbook workbook) {

        Map<TextFormat, Map<PredefinedColors, CellStyle>> styles = new HashMap<>();

        Map<TextFormat, Short> textFormat = new HashMap<>();
        textFormat.put(TextFormat.TEXT_ONLY, workbook.createDataFormat().getFormat("@"));
        textFormat.put(TextFormat.CURRENCY, workbook.createDataFormat().getFormat("#,##0.00 €"));
        textFormat.put(TextFormat.PERCENTAGE, workbook.createDataFormat().getFormat("0.00%"));

        var fontStyle = createFontStyle(workbook, false);
        var headerFontStyle = createFontStyle(workbook, true);

        for (TextFormat currentFormat : TextFormat.values()) {

            Map<PredefinedColors, CellStyle> colors = new HashMap<>();

            for (PredefinedColors color : PredefinedColors.values()) {

                CellStyle style = createStyle(workbook, textFormat.get(currentFormat), color.getBold() ? headerFontStyle : fontStyle);
                colors.put(color, updateHighlight(style, color));

            }

            styles.put(currentFormat, colors);
        }

        return styles;
    }


    public enum TextFormat {
        TEXT_ONLY,
        CURRENCY,
        PERCENTAGE,
    }

    public enum PredefinedColors {
        HEADER(true, new XSSFColor(new byte[]{(byte) 195, (byte) 207, (byte) 223}, null)),
        SUB_HEADER(true, new XSSFColor(new byte[]{(byte) 220, (byte) 227, (byte) 236}, null)),
        LIGHT_BLUE_1(true, new XSSFColor(new byte[]{(byte) 220, (byte) 227, (byte) 236}, null)),
        LIGHT_BLUE_2(true, new XSSFColor(new byte[]{(byte) 195, (byte) 207, (byte) 223}, null)),
        GREEN_1(false, new XSSFColor(new byte[]{(byte) 160, (byte) 246, (byte) 211}, null)),
        GREEN_2(false, new XSSFColor(new byte[]{(byte) 90, (byte) 240, (byte) 180}, null)),
        TITLE(true, new XSSFColor(new byte[]{(byte) 0, (byte) 47, (byte) 84}, null)),
        NEUTRAL(false, new XSSFColor(new byte[]{(byte) 255, (byte) 255, (byte) 255}, null)),
        EXCEPTION(false, new XSSFColor(new byte[]{(byte) 188, (byte) 43, (byte) 114}, null));

        final XSSFColor color;
        private final boolean bold;

        PredefinedColors(boolean bold, XSSFColor xssfColor) {
            this.color = xssfColor;
            this.bold = bold;
        }

        public XSSFColor getColor() {
            return color;
        }

        public boolean getBold() { return bold; }
    }

}
