package com.fs.watch.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TimestampArrayTypeHandler extends BaseTypeHandler<List<String>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            ps.setArray(i, null);
        } else {
            Timestamp[] array = parameter.stream()
                    .map(ts -> Timestamp.valueOf(ts))
                    .toArray(Timestamp[]::new);
            ps.setArray(i, ps.getConnection().createArrayOf("TIMESTAMP", array));
        }
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Array array = rs.getArray(columnName);
        if (array == null) {
            return null;
        }
        Timestamp[] result = (Timestamp[]) array.getArray();
        return Arrays.stream(result)
                .map(ts -> convertToLocalTime(ts.toInstant()))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Array array = rs.getArray(columnIndex);
        if (array == null) {
            return null;
        }
        Timestamp[] result = (Timestamp[]) array.getArray();
        return Arrays.stream(result)
                .map(ts -> convertToLocalTime(ts.toInstant()))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Array array = cs.getArray(columnIndex);
        if (array == null) {
            return null;
        }
        Timestamp[] result = (Timestamp[]) array.getArray();
        return Arrays.stream(result)
                .map(ts -> convertToLocalTime(ts.toInstant()))
                .collect(Collectors.toList());
    }

    private String convertToLocalTime(Instant instant) {
        // Convert to LocalDateTime in system default time zone
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        // Format to string
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}
