<?php

namespace FleekDash\API\Posts;

use DateTime;
use Exception;

/**
 * Posts Data Formatter
 *
 * Handles formatting of post data for API responses
 *
 * @package FleekDash\API\Posts
 */
class PostsDataFormatter
{
    /**
     * Get relative time string from date
     *
     * Uses calendar days for day calculations, not time difference
     * This ensures "2d ago" when the date is 2 calendar days in the past,
     * regardless of the specific time of day.
     *
     * @param string $date_string Date string to convert
     * @return string Relative time (e.g., "2h ago", "in 3d")
     */
    public static function getRelativeTime($date_string)
    {
        try {
            $date = new DateTime($date_string);
            $now = new DateTime();

            $diff_seconds = $now->getTimestamp() - $date->getTimestamp();

            // For hours and minutes, use time-based calculation
            // This is accurate for same-day events
            if (abs($diff_seconds) < 86400) {
                // Handle future dates (within 24 hours)
                if ($diff_seconds < 0) {
                    $diff = abs($diff_seconds);
                    if ($diff < 60) {
                        return 'in a moment';
                    } elseif ($diff < 3600) {
                        $minutes = floor($diff / 60);
                        return 'in ' . $minutes . 'm';
                    } else {
                        $hours = floor($diff / 3600);
                        return 'in ' . $hours . 'h';
                    }
                }

                // Handle past dates (within 24 hours)
                if ($diff_seconds < 60) {
                    return 'just now';
                } elseif ($diff_seconds < 3600) {
                    $minutes = floor($diff_seconds / 60);
                    return $minutes . 'm ago';
                } else {
                    $hours = floor($diff_seconds / 3600);
                    return $hours . 'h ago';
                }
            }

            // For days, use calendar day calculation (normalize to midnight)
            // This ensures consistent day counting regardless of time of day
            $date_midnight = new DateTime($date->format('Y-m-d'));
            $now_midnight = new DateTime($now->format('Y-m-d'));

            // Calculate diff from date to now (not now to date)
            // This ensures: positive = date is in the past, negative = date is in the future
            // When date is in past: past->diff(now) = positive interval (2) → "2d ago"
            // When date is in future: future->diff(now) = negative interval (-2) → "in 2d"
            $interval = $date_midnight->diff($now_midnight);
            $diff_days = (int) $interval->format('%r%a');

            // Handle future dates (days) - diff_days is negative when date is in the future
            if ($diff_days < 0) {
                $abs_days = abs($diff_days);
                if ($abs_days < 30) {
                    return 'in ' . $abs_days . 'd';
                } else {
                    // For future dates beyond 30 days, return formatted date
                    $year_diff = $now->format('Y') !== $date->format('Y');
                    if ($year_diff) {
                        return $date->format('M j, Y');
                    } else {
                        return $date->format('M j');
                    }
                }
            }

            // Handle past dates (days) - diff_days is positive when date is in the past
            if ($diff_days < 30) {
                return $diff_days . 'd ago';
            } else {
                // For older dates, return formatted date
                $year_diff = $now->format('Y') !== $date->format('Y');
                if ($year_diff) {
                    return $date->format('M j, Y');
                } else {
                    return $date->format('M j');
                }
            }
        } catch (Exception $e) {
            return 'Invalid date';
        }
    }

    /**
     * Get post image data with proper priority order
     *
     * Priority: logo → featured image → attached images → none
     *
     * @param int $post_id The post ID
     * @return array Array with 'url' and 'type' keys
     */
    public static function getPostImageData($post_id)
    {
        // Helper to pick the smallest available image URL for an attachment
        $get_smallest_available_image_url = function ($attachment_id) {
            if (!$attachment_id) {
                return '';
            }

            // Preferred custom size
            $url = is_callable('wp_get_attachment_image_url') ? \call_user_func('wp_get_attachment_image_url', $attachment_id, 'fleekdash-thumbnail') : '';
            if ($url) {
                return $url;
            }

            // Inspect metadata to find the smallest registered intermediate size
            $meta = is_callable('wp_get_attachment_metadata') ? \call_user_func('wp_get_attachment_metadata', $attachment_id) : array();
            if (!empty($meta) && isset($meta['sizes']) && is_array($meta['sizes'])) {
                $sizeToArea = [];
                foreach ($meta['sizes'] as $sizeName => $info) {
                    if (isset($info['width'], $info['height'])) {
                        $sizeToArea[$sizeName] = (int) $info['width'] * (int) $info['height'];
                    }
                }
                if (!empty($sizeToArea)) {
                    asort($sizeToArea);
                    foreach (array_keys($sizeToArea) as $sizeName) {
                        $url = is_callable('wp_get_attachment_image_url') ? \call_user_func('wp_get_attachment_image_url', $attachment_id, $sizeName) : '';
                        if ($url) {
                            return $url;
                        }
                    }
                }
            }

            // Conservative fallbacks
            foreach (['thumbnail', 'medium', 'medium_large', 'large'] as $fallbackSize) {
                $url = is_callable('wp_get_attachment_image_url') ? \call_user_func('wp_get_attachment_image_url', $attachment_id, $fallbackSize) : '';
                if ($url) {
                    return $url;
                }
            }

            return is_callable('wp_get_attachment_url') ? (\call_user_func('wp_get_attachment_url', $attachment_id) ?: '') : '';
        };

        // Check for logo first (meta field "logo")
        $logo_id = \get_post_meta($post_id, 'logo', true);
        if ($logo_id) {
            $logo_url = $get_smallest_available_image_url($logo_id);
            if ($logo_url) {
                return [
                    'url' => $logo_url,
                    'type' => 'logo'
                ];
            }
        }

        // Check for featured image
        if (is_callable('has_post_thumbnail') && \call_user_func('has_post_thumbnail', $post_id)) {
            $thumbnail_id = is_callable('get_post_thumbnail_id') ? \call_user_func('get_post_thumbnail_id', $post_id) : 0;
            if ($thumbnail_id) {
                $thumbnail_url = $get_smallest_available_image_url($thumbnail_id);

                if ($thumbnail_url) {
                    return [
                        'url' => $thumbnail_url,
                        'type' => 'featured'
                    ];
                }
            }
        }

        // Check for attached images
        $attached_images = is_callable('get_attached_media') ? \call_user_func('get_attached_media', 'image', $post_id) : array();
        if (!empty($attached_images)) {
            $first_image = reset($attached_images);
            $image_url = $get_smallest_available_image_url($first_image->ID);

            if ($image_url) {
                return [
                    'url' => $image_url,
                    'type' => 'attached'
                ];
            }
        }

        // Return empty string to let the grid use its native placeholder
        return [
            'url' => '',
            'type' => 'none'
        ];
    }
}
