<?php

namespace Fotogenic_AI;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class Service_Generate_Remove {
    private ?ProductMediaWriteAdapter $product_media_write_adapter;

    public function __construct( ?ProductMediaWriteAdapter $product_media_write_adapter ) {
        $this->product_media_write_adapter = $product_media_write_adapter;
    }

    /** @return \WP_REST_Response|\WP_Error */
    public function remove( array $data, int $user_id ) {
        $attachment_ids = isset( $data['attachmentIds'] ) && is_array( $data['attachmentIds'] )
            ? $data['attachmentIds']
            : [];
        $authorization = ( new Workflow_Response_Factory() )->authorize_mutation( $data, 'delete', $attachment_ids, $user_id );
        if ( is_wp_error( $authorization ) ) {
            return $authorization;
        }
        if ( 1 !== count( $authorization['attachment_ids'] ) ) {
            return Messages::error( 'invalid_request', 400 );
        }

        $attachment_id = (int) $authorization['attachment_ids'][0];
        if ( ! get_post( $attachment_id ) ) {
            return rest_ensure_response(
                [
                    'status'  => 'removed',
                    'changed' => false,
                ]
            );
        }

        return $this->remove_attachment( $attachment_id, $authorization['row'] );
    }

    /** @return \WP_REST_Response|\WP_Error */
    private function remove_attachment( int $attachment_id, array $run_row = [] ) {
        $product_ids = $this->find_related_product_ids_for_attachment( $attachment_id );
        $product_targets = $this->resolve_product_targets( $product_ids );
        if ( is_wp_error( $product_targets ) ) {
            return $product_targets;
        }
        $authorization = $this->authorize_content_subject( $attachment_id, $run_row );
        if ( is_wp_error( $authorization ) ) {
            return $authorization;
        }
        if ( ! empty( $product_targets ) ) {
            if ( null === $this->product_media_write_adapter ) {
                return new \WP_Error(
                    'fotogenic_ai_result_delivery_unavailable',
                    __( 'The Product destination is unavailable.', 'fotogenic-ai' ),
                    [ 'status' => 503 ]
                );
            }
            $detached = $this->product_media_write_adapter->remove_attachment_from_targets( $product_targets, $attachment_id );
            if ( is_wp_error( $detached ) ) {
                return $detached;
            }
        }
        $target     = sanitize_key( (string) ( $run_row['run_target'] ?? '' ) );
        $subject_id = absint( $run_row['subject_id'] ?? 0 );
        if ( in_array( $target, [ 'post', 'page' ], true ) && (int) get_post_thumbnail_id( $subject_id ) === $attachment_id ) {
            delete_post_thumbnail( $subject_id );
        }
        if ( ! wp_delete_attachment( $attachment_id, true ) ) {
            return Messages::error( 'request_failed', 500 );
        }
        Bulk_Repo::instance()->clear_attachment_references( $attachment_id );
        if ( ! empty( $product_targets ) ) {
            Studio_Cache_Store::flush_all_caches();
        }
        if ( in_array( $target, [ 'media', 'post', 'page' ], true ) && $subject_id > 0 ) {
            clean_post_cache( $subject_id );
        }

        return rest_ensure_response(
            [
                'status'  => 'removed',
                'changed' => true,
            ]
        );
    }

    /**
     * Resolve and authorize every Product destination before any mutation.
     *
     * @param int[] $product_ids Related Product or variation IDs.
     * @return array[]|\WP_Error
     */
    private function resolve_product_targets( array $product_ids ) {
        $targets = [];
        foreach ( $product_ids as $product_id ) {
            $target = Workflow_Item_Identity::resolve_target( 'product', absint( $product_id ) );
            if ( is_wp_error( $target ) ) {
                return $target;
            }
            $targets[] = $target;
        }
        return $targets;
    }

    /** @return true|\WP_Error */
    private function authorize_content_subject( int $attachment_id, array $run_row ) {
        $target     = sanitize_key( (string) ( $run_row['run_target'] ?? '' ) );
        $subject_id = absint( $run_row['subject_id'] ?? 0 );
        if ( ! in_array( $target, [ 'post', 'page' ], true ) || $subject_id < 1 ) {
            return true;
        }
        $subject = get_post( $subject_id );
        if (
            $subject
            && $target === (string) ( $subject->post_type ?? '' )
            && (int) get_post_thumbnail_id( $subject_id ) === $attachment_id
            && ! current_user_can( 'edit_post', $subject_id )
        ) {
            return new \WP_Error(
                'fotogenic_ai_result_subject_forbidden',
                __( 'You cannot remove this image because its related content cannot be edited.', 'fotogenic-ai' ),
                [ 'status' => 403 ]
            );
        }

        return true;
    }

    /**
     * Find products that currently reference this attachment as featured or gallery image.
     *
     * @return int[]
     */
    private function find_related_product_ids_for_attachment( int $attachment_id ): array {
        $attachment_id = absint( $attachment_id );
        if ( $attachment_id <= 0 ) {
            return [];
        }
        global $wpdb;
        if ( ! isset( $wpdb->postmeta, $wpdb->posts ) ) {
            return [];
        }
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- One-off cleanup lookup against core post/postmeta tables during attachment removal.
        $rows = (array) $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT pm.post_id
                FROM {$wpdb->postmeta} pm
                INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                WHERE p.post_status <> 'trash'
                  AND (
                    (p.post_type IN ('product', 'product_variation') AND pm.meta_key = '_thumbnail_id' AND pm.meta_value = %d)
                    OR
                    (p.post_type = 'product' AND pm.meta_key = '_product_image_gallery' AND FIND_IN_SET(%d, pm.meta_value) > 0)
                  )",
                $attachment_id,
                $attachment_id
            )
        );
        return array_values( array_unique( array_filter( array_map( 'absint', $rows ) ) ) );
    }
}
