<?php

// Prevent direct access to the file
if (!defined('ABSPATH')) {
    exit;
}

// Include necessary files
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');

class ScrobbleHandler {
    private $auth_key;
    private $option_name = 'image_scrobble_auth_key';

    public function __construct() {
        $this->auth_key = get_option($this->option_name);
        
        add_action('rest_api_init', array($this, 'register_routes'));
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('admin_init', array($this, 'register_settings'));
        register_activation_hook(__FILE__, array($this, 'activate_plugin'));
    }

    public function activate_plugin() {
        // Set default AUTH_KEY if not exists
        if (!get_option($this->option_name)) {
            update_option($this->option_name, wp_generate_password(32, false));
        }
    }

    public function register_routes() {
        register_rest_route('image-scrobble/v1', '/create', array(
            'methods' => 'POST',
            'callback' => array($this, 'create_image'),
            'permission_callback' => array($this, 'check_auth')
        ));

        register_rest_route('image-scrobble/v1', '/scrobble', array(
            'methods' => 'POST',
            'callback' => array($this, 'scrobble'),
            'permission_callback' => array($this, 'check_auth')
        ));
    }

    public function check_auth($request) {
        $auth_header = $request->get_header('Authorization');
        return $auth_header && $auth_header === "Bearer {$this->auth_key}";
    }

    public function create_image($request) {
    // Retrieve the raw image data from the request body
    $image_data = $request->get_body();

    // Sanitize and retrieve parameters from the request
    $author = sanitize_text_field($request->get_param('author'));
    $album_title = sanitize_text_field($request->get_param('album_title'));
    $song_title = sanitize_text_field($request->get_param('song_title')); // New parameter

    // Validate required parameters
    if (empty($author)) {
        return new WP_Error(
            'missing_author',
            'Author is required.',
            array('status' => 400)
        );
    }

    // Ensure that either album_title or song_title is provided
    if (empty($album_title) && empty($song_title)) {
        return new WP_Error(
            'missing_titles',
            'Either album title or song title is required.',
            array('status' => 400)
        );
    }

    // Determine which title to use: album_title takes precedence over song_title
    $title = !empty($album_title) ? $album_title : $song_title;

    // Generate a hash of the image data to check for duplicates
    $image_hash = md5($image_data);

    // Check if an image with this hash already exists to prevent duplicates
    $existing_attachment = $this->get_attachment_by_hash($image_hash);
    if ($existing_attachment) {
        return new WP_REST_Response(
            array('url' => wp_get_attachment_url($existing_attachment->ID)),
            200
        );
    }

    // Get the upload directory information
    $upload_dir = wp_upload_dir();

    // Create a sanitized filename using the author and the determined title
    $filename = sanitize_file_name("{$author} - {$title}.jpg");

    // Ensure the filename is unique within the upload directory
    $unique_filename = wp_unique_filename($upload_dir['path'], $filename);

    // Construct the full file path
    $file_path = trailingslashit($upload_dir['path']) . $unique_filename;

    // Attempt to save the image data to the specified file path
    if (file_put_contents($file_path, $image_data) === false) {
        return new WP_Error(
            'file_save_failed',
            'Failed to save the image file.',
            array('status' => 500)
        );
    }

    // Prepare the attachment data
    $attachment = array(
        'post_mime_type' => 'image/jpeg',
        'post_title'     => "{$author} - {$title}",
        'post_content'   => '',
        'post_status'    => 'inherit'
    );

    // Insert the attachment into the WordPress media library
    $attach_id = wp_insert_attachment($attachment, $file_path);

    // Check for errors during attachment insertion
    if (is_wp_error($attach_id)) {
        @unlink($file_path); // Clean up the file if attachment creation failed
        return $attach_id;    // Return the WP_Error
    }

    // Generate and update attachment metadata
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    $attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
    wp_update_attachment_metadata($attach_id, $attach_data);

    // Save the image hash in the attachment's metadata for future duplicate checks
    update_post_meta($attach_id, 'image_hash', $image_hash);

    // Retrieve the URL of the newly created attachment
    $image_url = wp_get_attachment_url($attach_id);

    // Return a successful response with the image URL
    return new WP_REST_Response(
        array('url' => $image_url),
        200
    );
}


    private function get_attachment_by_hash($hash) {
        $args = array(
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'posts_per_page' => 1,
            'meta_query' => array(
                array(
                    'key' => 'image_hash',
                    'value' => $hash,
                    'compare' => '='
                )
            )
        );

        $query = new WP_Query($args);

        if ($query->have_posts()) {
            return $query->posts[0];
        }

        return null;
    }

public function scrobble($request) {
    global $wpdb;
    $data = $request->get_json_params();
    
    // Updated required fields: 'album_name' is no longer required
    $required_fields = ['song_name', 'author'];

    // Check for missing required fields
    foreach ($required_fields as $field) {
        if (!isset($data[$field])) {
            return new WP_Error('missing_field', 'Missing required field: ' . $field, array('status' => 400));
        }
    }

    $table_name = 'song_scrobbles';
    $cover_url = isset($data['cover_url']) ? $data['cover_url'] : null;
    $album_name = isset($data['album_name']) ? $data['album_name'] : null;

    // If 'album_name' is not provided, 'cover_url' must be present
    if (empty($album_name)) {
        if (empty($cover_url)) {
            return new WP_Error(
                'missing_cover_url', 
                'Cover URL must be provided if album name is not present', 
                array('status' => 400)
            );
        }
    } else {
        // If 'album_name' is provided but 'cover_url' is not, attempt to retrieve it from existing entries
        if (empty($cover_url)) {
            // Prepare case-insensitive search
            $song_name_lower = strtolower($data['song_name']);
            $album_name_lower = strtolower($album_name);
            $author_lower = strtolower($data['author']);

            // Query to find the most recent matching entry
            $query = $wpdb->prepare(
                "SELECT cover_url FROM $table_name 
                 WHERE LOWER(album_name) = %s AND LOWER(author) = %s 
                 ORDER BY id DESC 
                 LIMIT 1",
                 $album_name_lower, $author_lower
            );

            $cover_url = $wpdb->get_var($query);

            // If no matching entry is found, return an error
            if (!$cover_url) {
                return new WP_Error(
                    'missing_cover_url', 
                    'Cover URL not provided and no existing entry found for the given album and author', 
                    array('status' => 400)
                );
            }
        }
    }

    // Insert the scrobble data into the database
    $result = $wpdb->insert(
        $table_name,
        array(
            'song_name'      => $data['song_name'],
            'album_name'     => $album_name, // This can be null
            'cover_url'      => $cover_url,
            'author'         => $data['author'],
            'length_seconds' => isset($data['length_seconds']) ? intval($data['length_seconds']) : null
        ),
        array('%s', '%s', '%s', '%s', '%d')
    );

    // Handle potential database insertion errors
    if ($result === false) {
        return new WP_Error('db_error', 'Error saving scrobble', array('status' => 500));
    }

    // Return a successful response
    return new WP_REST_Response(array('message' => 'Scrobble saved successfully'), 201);
}


    public function add_admin_menu() {
        add_options_page(
            'Image Scrobble Settings',
            'Image Scrobble',
            'manage_options',
            'image-scrobble-settings',
            array($this, 'settings_page')
        );
    }

    public function register_settings() {
        register_setting('image_scrobble_settings', $this->option_name);
    }

    public function settings_page() {
        ?>
        <div class="wrap">
            <h1>Image Scrobble Settings</h1>
            <form method="post" action="options.php">
                <?php
                settings_fields('image_scrobble_settings');
                do_settings_sections('image_scrobble_settings');
                ?>
                <table class="form-table">
                    <tr valign="top">
                        <th scope="row">AUTH_KEY</th>
                        <td>
                            <input type="text" name="<?php echo $this->option_name; ?>" value="<?php echo esc_attr(get_option($this->option_name)); ?>" />
                        </td>
                    </tr>
                </table>
                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }
}

// Initialize the plugin
new ScrobbleHandler();
