<?php

namespace RtmBusiness\PostSync\SyncHandlers;

use RtmBusiness\PostSync\Logger;
use WP_Error;

class ImageSyncHandler extends AbstractSyncHandler
{

    /**
     * @inheritDoc
     */
    public function handle($sourceBlogId, $sourcePostId, $targetBlogId, $targetPostId): void
    {
        global $rtm_source_postdata;
        //Retrieve the fetched post data from the global variable populated by the 'postsync_before_sync' action
        $sourcePostData = $rtm_source_postdata['sourcePostData'];
        $formattedSourceAttachments = $rtm_source_postdata['formattedSourceAttachments'];
        $sourceThumbnailId = $rtm_source_postdata['sourceThumbnailId'];

        $copyMedia = get_site_option('postsync_copy_media', false) == 1;

        //Handling of images
        $imageUrlMap = [];
        $galleryImagesMapping = [];
        $targetThumbnailId = null;
        foreach ($formattedSourceAttachments as $imageData) {
            $fileName = $imageData['filename'];
            $fileHash = md5_file($fileName);

            $sameHashAttachmentQuery = [
                'post_type' => 'attachment',
                'post_status' => 'inherit',
                'post_parent' => $targetPostId,
                'posts_per_page' => 1,
                'meta_query' => [
                    [
                        'key' => 'filehash',
                        'value' => $fileHash,
                        'compare' => '=',
                    ]
                ]
            ];

            //Get all the images on target blog with the same hash as source blog image
            $duplicateImages = get_posts($sameHashAttachmentQuery);

            //If there are duplicate images, check if the file path is refering to parent file or uploaded file
            foreach ($duplicateImages as $key => $image) {
                // Get the metadata of the attachment
                $meta = get_post_meta($image->ID, '_wp_attachment_metadata', true);

                if ($copyMedia === true) {
                    //If the file path contains this relative path, it means it wasnt uploaded so we can't use it
                    if (str_contains($meta['file'], '../../')) {
                        unset($duplicateImages[$key]);
                    }
                } else {
                    //If the file path does not contain this relative path, the attachment is not a reference to parent file so we can't use it
                    if (!str_contains($meta['file'], '../../')) {
                        unset($duplicateImages[$key]);
                    }
                }
            }
            // Re-index the array
            $duplicateImages = array_values($duplicateImages);

            $fileType = wp_check_filetype(basename($fileName));

            // Create a temporary copy because media_handle_sideload() will move the file
            $tempFileName = tempnam(sys_get_temp_dir(), 'tmp');
            copy($fileName, $tempFileName);

            $file = [
                'name' => basename($fileName),
                'type' => $fileType['type'],
                'tmp_name' => $tempFileName,
                'error' => 0,
                'size' => filesize($fileName),
            ];

            if (!file_exists($tempFileName)) {
                continue;
            }

            if (!empty($duplicateImages)) {
                $targetAttachmentId = $duplicateImages[0]->ID;
            } else {
                if ($copyMedia === false) {
                    $originalImageMeta = $imageData['meta'];

                    //Insert attachment on target blog without copying the file
                    $targetAttachmentId = $this->insertAttachmentFromExistingFile($fileName, $targetPostId);
                    wp_update_attachment_metadata($targetAttachmentId, $originalImageMeta);

                    //Update the path to exclude /sites/{site_id}/ from the path if the target blog is not the main site
                    if ($targetBlogId != get_main_site_id()) {
                        $file_path = '../../' . $imageData['file_path'];
                    } else {
                        $file_path = str_replace('../../', '', $imageData['file_path']);
                    }
                    update_post_meta($targetAttachmentId, '_wp_attached_file', $file_path);

                    // Determine the base directory of the old and new file paths.
                    $oldBaseDir = trailingslashit(pathinfo($imageData['file_path'], PATHINFO_DIRNAME));
                    $newBaseDir = trailingslashit(pathinfo($file_path, PATHINFO_DIRNAME));

                    //Replace old base directory with new base directory in the file path
                    $originalImageMeta['file'] = str_replace($oldBaseDir, $newBaseDir, $originalImageMeta['file']);
                    update_post_meta($targetAttachmentId, '_wp_attachment_metadata', $originalImageMeta);

                } else {
                    //REST API does not load the media_handle_sideload() function, so we need to load its dependencies manually
                    if (!function_exists('media_handle_sideload')) {
                        require_once(ABSPATH . 'wp-admin/includes/file.php');
                        require_once(ABSPATH . 'wp-admin/includes/media.php');
                        require_once(ABSPATH . 'wp-admin/includes/image.php');
                    }
                    $targetAttachmentId = media_handle_sideload($file, $targetPostId);
                }
            }

            if (is_wp_error($targetAttachmentId)) {
                // Log error or handle it as you wish
                Logger::error("Attachment Upload Failed", "Uploading the attachment to child blog has failed", "PublishAction", 'sync', [
                    'uploadingTo' => $targetBlogId,
                    'error' => $targetAttachmentId->get_error_messages(),
                    'stackTrace' => $targetAttachmentId->get_error_data(),
                    'file' => $file,
                ]);
            } else {
                if ($imageData['is_gallery'] === true) {
                    $galleryImagesMapping[] = $targetAttachmentId;
                }
                $newImageUrl = wp_get_attachment_url($targetAttachmentId);
                $oldImageUrl = $imageData['url'];
                $imageUrlMap[$oldImageUrl] = $newImageUrl;
                // If the current image is the thumbnail, update the target thumbnail ID.
                if ($sourceThumbnailId === $imageData['attachment']->ID) {
                    $targetThumbnailId = $targetAttachmentId;
                }
                update_post_meta($targetAttachmentId, 'filehash', $fileHash);
            }


            // If original file was moved, restore it from the temporary copy
            if (!file_exists($fileName)) {
                copy($tempFileName, $fileName);
            }

            // Delete the temporary file
            unlink($tempFileName);
        }
        //Update the gallery image ids on the target post
        if ($galleryImagesMapping) {
            update_post_meta($targetPostId, '_product_image_gallery', implode(',', $galleryImagesMapping));
        }
        //Replace reference to old image url with new image url
        if ($copyMedia) {
            if ($targetBlogId != get_main_site_id()) {
                //Syncing from child to child
                if ($sourceBlogId != get_main_site_id()) {
                    $sourcePostData['post_content'] = preg_replace('/\/uploads\/sites\/\d+\//', "/uploads/sites/$targetBlogId/", $sourcePostData['post_content']);
                } else { //Syncing from main to child
                    $sourcePostData['post_content'] = str_replace('/uploads/', "/uploads/sites/$targetBlogId/", $sourcePostData['post_content']);
                }
            } else { //Syncing to main
                $sourcePostData['post_content'] = preg_replace('/\/uploads\/sites\/\d+\//', "/uploads/", $sourcePostData['post_content']);
            }
        }

        //Set ID so correct post content gets updated
        $sourcePostData['ID'] = $targetPostId;
        //Update the post content with the new post content which has the new image urls
        wp_update_post($sourcePostData);
        // Setting the featured image on the target post if source post has a featured image
        if ($sourceThumbnailId && $targetThumbnailId) {
            // Set the featured image on the target post
            set_post_thumbnail($targetPostId, $targetThumbnailId);
        }
    }


    /**
     * Insert an attachment from an existing file.
     * @param string $full_path The path to the file to make an attachment from.
     * @param int $post_id The parent post ID for the new attachment.
     * @return WP_Error|int Attachment ID on success, WP_Error otherwise.
     */
    public function insertAttachmentFromExistingFile(string $full_path, int $post_id = 0): WP_Error|int
    {
        $filename = basename($full_path);

        // Make sure the file exists
        if (!file_exists($full_path)) {
            return new WP_Error('file_not_found', "File doesn't exist");
        }

        $wp_filetype = wp_check_filetype($filename);
        $attachment = [
            'post_mime_type' => $wp_filetype['type'],
            'post_parent' => $post_id,
            'post_title' => preg_replace('/\.[^.]+$/', '', $filename),
            'post_content' => '',
            'post_status' => 'inherit'
        ];
        return wp_insert_attachment($attachment, $full_path, $post_id);
    }
}
