package de.avatic.taricdb.helper.workbook;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;

public class ExcelRow {
	
	private static final String DATE_FORMAT = "dd-MM-yyyy";
	private static final String DATE_FORMAT2 = "dd.MM.yyyy";
	private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
	private static final DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern(DATE_FORMAT2);
	

	private List<String> values = new ArrayList<>();
	
	private ExcelHeader header;

	private int index;
	
	private Row row;
	
	private List<LocalDate> date;
	
	/**
	 * Constructor for the ExcelRow class.
	 * It processes a given Excel row and extracts cell values, converting them to appropriate formats,
	 * and associates them with an Excel header for mapping column indices.
	 *
	 * @param row the Excel row object to be processed, represented as a {@link Row}.
	 * @param header the ExcelHeader object containing header information for column mappings.
	 * @throws IllegalArgumentException if a cell type in the row is unsupported.
	 */
	public ExcelRow(Row row, ExcelHeader header) {
		this.date = new ArrayList<>();
		this.row = row;
		
		row.cellIterator().forEachRemaining(cell -> {
			LocalDate cellDate = null;
			
			switch(cell.getCellType())
			{
			case NUMERIC:
				double value = cell.getNumericCellValue();
				
				if(DateUtil.isCellDateFormatted(cell))
				{
					cellDate = cell.getLocalDateTimeCellValue().toLocalDate();
				} 
				if(isInteger(value)) {
                    values.add(String.valueOf((int)value));
                } else {
                    values.add(String.valueOf(value));
                }
			
				break;
			case BLANK:
			case STRING:
                values.add(cell.getStringCellValue());
                break;
			default:
				throw new IllegalArgumentException("Unsupported cell type: " + cell.getCellType());
			}
			
			date.add(cellDate);
		});
		
		this.header = header;
		this.index = row.getRowNum();
	
	}
	
	public boolean isInteger(double number){
	    return Math.ceil(number) == Math.floor(number); 
	}



	/**
	 * Retrieves the value of a specific column from the Excel row and converts it to the specified type.
	 *
	 * @param string the name of the column to retrieve the value from
	 * @param clazz the class type to which the value will be converted; supported types are String, Integer, Boolean, and LocalDate
	 * @return the value of the column converted to the specified type, or null if the column value is empty or invalid for the requested type
	 * @throws IllegalArgumentException if the column with the specified name is not found in the header
	 */
	@SuppressWarnings("unchecked")
	public <T> T getAs(String string, Class<T> clazz) {
		int columnIdx = getColumnIdx(string.trim()); 
				
		
		if (columnIdx == -1) {
			throw new IllegalArgumentException("Column " + string + " not found, available columns are: " + header);
		}
		
		if ( clazz == String.class) {
            return (T) values.get(columnIdx);
        }
		
		if (clazz == Integer.class) {
			if (values.get(columnIdx).isEmpty()) {
				return null;
			}

			return (T) Integer.valueOf(values.get(columnIdx));
		}
		
		if (clazz == Boolean.class) {
			if (values.get(columnIdx).isEmpty()) {
				return null;
			}

			return (T) Boolean.valueOf(Integer.valueOf(values.get(columnIdx)) == 1);
		}
		
		if (clazz == LocalDate.class) {
			
			
			if (this.date.get(columnIdx) != null) {
				return (T) this.date.get(columnIdx);
			}
			
			if (values.get(header.getIndex(string)).isEmpty()) {
				return null;
			}		
			
			try {
                return (T) LocalDate.parse(values.get(columnIdx), formatter2);
            } catch (Exception e) {
            	return (T) LocalDate.parse(values.get(columnIdx), formatter);
            }		
		}
		
		return null;
	}
	
	/**
	 * Retrieves the column index associated with the specified column name
	 * from the header information of an Excel sheet.
	 *
	 * @param string the name of the column whose index is to be retrieved
	 * @return the index of the specified column, or -1 if the column name
	 *         is not found in the header
	 */
	private int getColumnIdx(String string) {
		int idx = header.getIndex(string);
		

		
		return idx;
	}



	/**
	 * Retrieves the index of the current Excel row.
	 *
	 * @return the index of the row as an integer
	 */
	public int index() {
		return index;
	}

}
