package nemosofts.streambox.utils;

import android.annotation.SuppressLint;

import androidx.annotation.NonNull;

import org.jetbrains.annotations.Contract;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class FormatUtils {

    private static final String TAG = "FormatUtils";

    private static final int MINUTE = 60;
    private static final int HOUR = 3600;
    private static final int DAY = 86400;
    private static final int WEEK = 604800;
    private static final int MONTH = 2629743; // Approximation for average month
    private static final int YEAR = 31556926; // Approximation for average year

    private FormatUtils() {
        throw new IllegalStateException("Utility class");
    }

    @NonNull
    public static String format(Number number) {
        if (number == null) {
            return "0";
        }

        char[] suffix = {' ', 'k', 'M', 'B', 'T', 'P', 'E'};
        long numValue = number.longValue();
        if (numValue == 0) {
            return "0";
        }

        int value = (int) Math.floor(Math.log10(Math.abs(numValue)));
        int base = value / 3;
        if (value >= 3 && base < suffix.length) {
            return new DecimalFormat("#0.0").format(numValue / Math.pow(10, (double) base * 3)) + suffix[base];
        } else {
            return new DecimalFormat("#,##0").format(numValue);
        }
    }

    @NonNull
    public static String formatFileSize(long size) {
        if (size <= 0) return "0 Bytes";
        final String[] units = new String[]{"Bytes", "kB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    @NonNull
    public static String formatFrameRate(float frameRate) {
        DecimalFormat decimalFormat = new DecimalFormat("#.#");
        return decimalFormat.format(frameRate);
    }

    @NonNull
    public static String formatTime(String time) {
        if (time == null || time.isEmpty()) {
            return "0";
        }

        try {
            int totalMinutes = Integer.parseInt(time);
            int hours = totalMinutes / MINUTE;
            int minutes = totalMinutes % MINUTE;
            return formatTimeHm(hours, minutes);
        } catch (NumberFormatException e) {
            return "0";
        }
    }

    @NonNull
    public static String formatTimeDuration(String timeString) {
        if (timeString == null || timeString.trim().isEmpty()) {
            return "0";
        }

        try {
            String[] timeParts = timeString.split(":");
            int hours = Integer.parseInt(timeParts[0]);
            int minutes = Integer.parseInt(timeParts[1]);
            int seconds = Integer.parseInt(timeParts[2]);
            return formatTimeHm(hours, minutes) + " " + seconds + "s";
        } catch (Exception e) {
            return "0";
        }
    }

    @NonNull
    public static String getTimestamp(String data, boolean is12h) {
        try {
            long timestamp = Long.parseLong(data);
            Date date = new Date(timestamp * 1000);
            SimpleDateFormat sdf;
            if (is12h) {
                sdf = new SimpleDateFormat("hh:mm a", Locale.getDefault()); // Changed to 12-hour format
            } else {
                sdf = new SimpleDateFormat("HH:mm", Locale.getDefault()); // 24-hour format
            }
            return sdf.format(date);
        } catch (Exception e) {
            return "";
        }
    }

    @NonNull
    public static String calculateTimeSpan(String inputDateStr) {
        final String NOT_AVAILABLE = " not available";

        if (inputDateStr == null || inputDateStr.trim().isEmpty()) {
            return NOT_AVAILABLE;
        }

        try {
            @SuppressLint("SimpleDateFormat")
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
            Date inputDate = dateFormat.parse(inputDateStr);
            if (inputDate == null) {
                return NOT_AVAILABLE;
            }

            long timeDifferenceInMillis = new Date().getTime() - inputDate.getTime();
            long seconds = timeDifferenceInMillis / 1000;
            return formatTimeSpan(seconds);
        } catch (Exception e) {
            return NOT_AVAILABLE;
        }
    }

    @NonNull
    public static String convertIntToDate(String convertDate, String pattern) {
        if (convertDate == null || convertDate.isEmpty()) {
            return " none";
        }

        if (convertDate.equals("null")) {
            return " Unlimited";
        }

        try {
            long timestamp = Long.parseLong(convertDate);
            Date date = new Date(timestamp * 1000);
            SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
            return " " + dateFormat.format(date);
        } catch (NumberFormatException e) {
            return " none";
        }
    }

    // Private data ---------------------------------------------------------------------------------
    @NonNull
    private static String formatTimeHm(int hours, int minutes) {
        if (hours > 0) {
            return hours + "h " + minutes + "m";
        } else if (minutes > 0) {
            return minutes + "m";
        } else {
            return "0";
        }
    }

    @NonNull
    @Contract(pure = true)
    private static String formatTimeSpan(long seconds) {
        if (seconds <= 1) {
            return " just now";
        }

        if (seconds < MINUTE) {
            return formatSeconds(seconds);
        } else if (seconds < HOUR) {
            return formatMinutes(seconds);
        } else if (seconds < DAY) {
            return formatHours(seconds);
        } else if (seconds < WEEK) {
            return formatDays(seconds);
        } else if (seconds < MONTH) {
            return formatWeeks(seconds);
        } else if (seconds < YEAR) {
            return formatMonths(seconds);
        } else {
            return formatYears(seconds);
        }
    }

    @NonNull
    @Contract(pure = true)
    private static String formatSeconds(long seconds) {
        return seconds + (seconds == 1 ? " sec ago" : " secs ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatMinutes(long seconds) {
        int min = (int) (seconds / MINUTE);
        return min + (min == 1 ? " min ago" : " mins ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatHours(long seconds) {
        int hours = (int) (seconds / HOUR);
        return hours + (hours == 1 ? " hour ago" : " hours ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatDays(long seconds) {
        int days = (int) (seconds / DAY);
        return days + (days == 1 ? " day ago" : " days ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatWeeks(long seconds) {
        int weeks = (int) (seconds / WEEK);
        return weeks + (weeks == 1 ? " week ago" : " weeks ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatMonths(long seconds) {
        int months = (int) (seconds / MONTH);
        return months + (months == 1 ? " month ago" : " months ago");
    }

    @NonNull
    @Contract(pure = true)
    private static String formatYears(long seconds) {
        int years = (int) (seconds / YEAR);
        return years + (years == 1 ? " year ago" : " years ago");
    }
}