package de.avatic.lcc.service.bulk;

import de.avatic.lcc.dto.bulk.BulkFileType;
import de.avatic.lcc.model.bulk.*;
import de.avatic.lcc.model.bulk.header.*;
import de.avatic.lcc.service.bulk.helper.HeaderCellStyleProvider;
import de.avatic.lcc.service.bulk.helper.HeaderGenerator;
import de.avatic.lcc.service.excelMapper.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.SheetVisibility;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

@Service
public class TemplateExportService {


    private final HeaderGenerator headerGenerator;
    private final HeaderCellStyleProvider headerCellStyleProvider;
    private final HiddenNodeExcelMapper hiddenNodeExcelMapper;
    private final HiddenCountryExcelMapper hiddenCountryExcelMapper;
    private final String sheetPassword;
    private final ContainerRateExcelMapper containerRateExcelMapper;
    private final MatrixRateExcelMapper matrixRateExcelMapper;
    private final MaterialExcelMapper materialExcelMapper;
    private final PackagingExcelMapper packagingExcelMapper;
    private final NodeExcelMapper nodeExcelMapper;

    public TemplateExportService(@Value("${lcc.bulk.sheet_password}") String sheetPassword, HeaderGenerator headerGenerator, HeaderCellStyleProvider headerCellStyleProvider, HiddenNodeExcelMapper hiddenNodeExcelMapper, HiddenCountryExcelMapper hiddenCountryExcelMapper, ContainerRateExcelMapper containerRateExcelMapper, MatrixRateExcelMapper matrixRateExcelMapper, MaterialExcelMapper materialExcelMapper, PackagingExcelMapper packagingExcelMapper, NodeExcelMapper nodeExcelMapper) {
        this.headerGenerator = headerGenerator;
        this.headerCellStyleProvider = headerCellStyleProvider;
        this.hiddenNodeExcelMapper = hiddenNodeExcelMapper;
        this.hiddenCountryExcelMapper = hiddenCountryExcelMapper;
        this.sheetPassword = sheetPassword;
        this.containerRateExcelMapper = containerRateExcelMapper;
        this.matrixRateExcelMapper = matrixRateExcelMapper;
        this.materialExcelMapper = materialExcelMapper;
        this.packagingExcelMapper = packagingExcelMapper;
        this.nodeExcelMapper = nodeExcelMapper;
    }

    public InputStreamSource generateTemplate(BulkFileType bulkFileType) {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             Workbook workbook = new XSSFWorkbook()) {

            Sheet sheet = workbook.createSheet(BulkFileTypes.valueOf(bulkFileType.name()).getSheetName());

            CellStyle style = headerCellStyleProvider.createHeaderCellStyle(workbook);


            if (bulkFileType.equals(BulkFileType.COUNTRY_MATRIX) || bulkFileType.equals(BulkFileType.NODE)) {
                var hiddenCountrySheet = workbook.createSheet(HiddenTableType.COUNTRY_HIDDEN_TABLE.getSheetName());
                hiddenCountryExcelMapper.fillSheet(hiddenCountrySheet, style);
                hiddenCountrySheet.protectSheet(sheetPassword);
                workbook.setSheetVisibility(workbook.getSheetIndex(hiddenCountrySheet), SheetVisibility.HIDDEN);
            } else if (bulkFileType.equals(BulkFileType.CONTAINER_RATE) || bulkFileType.equals(BulkFileType.PACKAGING)) {
                var hiddenNodeSheet = workbook.createSheet(HiddenTableType.NODE_HIDDEN_TABLE.getSheetName());
                hiddenNodeExcelMapper.fillSheet(hiddenNodeSheet, style, BulkFileType.PACKAGING.equals(bulkFileType));
                hiddenNodeSheet.protectSheet(sheetPassword);
                workbook.setSheetVisibility(workbook.getSheetIndex(hiddenNodeSheet), SheetVisibility.HIDDEN);
            }

            // Create headers and constraints based on the bulk file type
            switch (bulkFileType) {
                case CONTAINER_RATE:
                    headerGenerator.generateHeader(sheet, ContainerRateHeader.class, style);
                    containerRateExcelMapper.createConstraints(workbook, sheet);
                    headerGenerator.fixWidth(sheet, ContainerRateHeader.class);
                    break;
                case COUNTRY_MATRIX:
                    headerGenerator.generateHeader(sheet, MatrixRateHeader.class, style);
                    matrixRateExcelMapper.createConstraints(workbook, sheet);
                    headerGenerator.fixWidth(sheet, MatrixRateHeader.class);
                    break;
                case MATERIAL:
                    headerGenerator.generateHeader(sheet, MaterialHeader.class, style);
                    materialExcelMapper.createConstraints(sheet);
                    headerGenerator.fixWidth(sheet, MaterialHeader.class);
                    break;
                case PACKAGING:
                    headerGenerator.generateHeader(sheet, PackagingHeader.class, style);
                    packagingExcelMapper.createConstraints(workbook, sheet);
                    headerGenerator.fixWidth(sheet, PackagingHeader.class);
                    break;
                case NODE:
                    headerGenerator.generateHeader(sheet, NodeHeader.class, style);
                    nodeExcelMapper.createConstraints(workbook, sheet);
                    headerGenerator.fixWidth(sheet, NodeHeader.class);
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported bulk file type: " + bulkFileType);
            }

            // Return the Excel file as an InputStreamSource
            workbook.write(outputStream);
            return new ByteArrayResource(outputStream.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("Failed to generate template", e);
        }

    }


}