<?php

declare(strict_types=1);

namespace SecurWP\Modules\Cloud\Services;

use SecurWP\Modules\Cloud\SecureApi;

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


class Repair {

    /** @var SecureApi */
    private $api;

    public function __construct( SecureApi $api ) {
        $this->api = $api;
    }

    /**
     * Request a repair URL for a specific file context.
     * 
     * @param string $type
     * @param string $slug
     * @param string $version
     * @param string $file_path
     * @param string $locale Optional locale used for localized WordPress core manifests.
     * @return string|false Download URL or false on failure.
     */
    public function get_download_url( string $type, string $slug, string $version, string $file_path, string $locale = '' ) {
        $payload = [
            'type'      => $type,
            'slug'      => $slug,
            'version'   => $version,
            'file_path' => $file_path,
        ];
        if ( $locale !== '' ) {
            $payload['locale'] = $locale;
        }

        $response = $this->api->post( 'repair/file', $payload );

        if ( is_wp_error( $response ) ) {
            securwp_log( 'Repair API Error: ' . $response->get_error_message() );
            return false;
        }

        if ( empty( $response['status'] ) || $response['status'] !== 'found' ) {
            if ( is_array( $response ) ) {
                $status = (string) ( $response['status'] ?? 'unknown' );
                $message = (string) ( $response['message'] ?? '' );
                securwp_log( 'Repair API Status: ' . $status . ( $message !== '' ? " ({$message})" : '' ) );
            }
            return false;
        }

        return $response['download_url'] ?? false;
    }

    /**
     * Download and replace a file with its clean version from the Vault.
     * 
     * @param string $abs_path Absolute path to the file to repair.
     * @param string $type Component type ('core', 'plugin', or 'theme').
     * @param string $slug Component slug (for example `wordpress`, `wordpress-es_ES`, or `files-man`).
     * @param string $version Component version.
     * @param string $rel_path Relative path within the component (e.g., 'wp-admin/index.php').
     * @param string $expected_hash Expected SHA-256 hash for integrity verification.
     * @param string $locale Optional locale used for localized WordPress core manifests.
     * @return bool|string True on success, error message on failure.
     */
    public function repair_file( string $abs_path, string $type, string $slug, string $version, string $rel_path, string $expected_hash, string $locale = '' ) {
        if ( ! file_exists( $abs_path ) && ! wp_is_writable( dirname( $abs_path ) ) ) {
             return 'Target directory is not writable.';
        }
        if ( file_exists( $abs_path ) && ! wp_is_writable( $abs_path ) ) {
            return 'Target file is not writable.';
        }
        if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
            return 'Invalid expected hash for repair verification.';
        }

        $url = $this->get_download_url( $type, $slug, $version, $rel_path, $locale );
        if ( ! $url ) {
            return 'Could not retrieve repair URL from Cloud Vault.';
        }

        $temp_file = download_url( $url );
        if ( is_wp_error( $temp_file ) ) {
            return 'Download failed: ' . $temp_file->get_error_message();
        }

        $download_hash = hash_file( 'sha256', $temp_file );
        if ( ! is_string( $download_hash ) || strtolower( $download_hash ) !== strtolower( $expected_hash ) ) {
            wp_delete_file( $temp_file );
            return 'Downloaded repair file failed integrity verification.';
        }

        global $wp_filesystem;
        if ( empty( $wp_filesystem ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }

        if ( ! $wp_filesystem->move( $temp_file, $abs_path, true ) ) {
             // Fallback to copy/unlink if move fails
             if ( ! copy( $temp_file, $abs_path ) ) {
                 wp_delete_file( $temp_file );
                 return 'Failed to overwrite file system.';
             }
             wp_delete_file( $temp_file );
        }

        if ( function_exists( 'opcache_invalidate' ) ) {
            @opcache_invalidate( $abs_path, true );
        }

        return true;
    }
}
