<?php

namespace MovieEngine\Api;

if (! defined("ABSPATH")) {
    exit; // Exit if accessed directly
}

class TmdbClient {

    private $api_key;
    private $base_url = 'https://api.themoviedb.org/3/';

    public function __construct() {
        $options = get_option('movie_engine_api_settings', []);
        $this->api_key = isset($options['movie_engine_tmdb_api_key']) ? sanitize_text_field($options['movie_engine_tmdb_api_key']) : '';
    }

    public function validate() {
        if (empty($this->api_key)) return false;

        $url = add_query_arg(['api_key' => $this->api_key], $this->base_url . 'configuration');
        $response = wp_remote_get($url, [
            'timeout'   => 15,
            'sslverify' => false
        ]);

        $trans_key = 'movie_engine_tmdb_error_' . md5($this->api_key);

        if (is_wp_error($response)) {
            set_transient($trans_key, $response->get_error_message(), HOUR_IN_SECONDS);
            return false;
        }

        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if (isset($data['status_code']) && $data['status_code'] !== 1) {
            $msg = $data['status_message'] ?? esc_html__('Invalid API Key', 'cine-movie-engine');
            set_transient($trans_key, $msg, HOUR_IN_SECONDS);
            return false;
        }

        if (isset($data['images'])) {
            delete_transient($trans_key);
            return true;
        }

        return false;
    }

    public function search_movie($query, $page = 1) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $args = [
            'api_key' => $this->api_key,
            'page'    => $page,
        ];

        if (is_numeric($query)) {
            $details = $this->get_movie_details($query);
            if (is_wp_error($details)) {
                return $details;
            }
            return ['page' => 1, 'results' => [$details], 'total_pages' => 1, 'total_results' => 1];
        }

        if (preg_match('/^tt\d+$/', $query)) {
            $result = $this->find_by_id($query, 'imdb_id');
            if (is_wp_error($result)) return $result;
            $movie = $result['movie_results'][0] ?? null;
            if (!$movie) return new \WP_Error('no_results', esc_html__('No movie found with this IMDb ID.', 'cine-movie-engine'));
            return ['page' => 1, 'results' => [$movie], 'total_pages' => 1, 'total_results' => 1];
        }

        if (preg_match('/^(.*?)\s*\((\d{4})\)$/', $query, $matches)) {
            $args['query'] = $matches[1];
            $args['year']  = $matches[2];
        } else {
            $args['query'] = $query;
        }

        $url = add_query_arg($args, $this->base_url . 'search/movie');
        return $this->make_request($url);
    }

    public function search_tv($query, $page = 1) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $args = [
            'api_key' => $this->api_key,
            'page'    => $page,
        ];

        if (is_numeric($query)) {
            $details = $this->get_tv_details($query);
            if (is_wp_error($details)) return $details;
            return ['page' => 1, 'results' => [$details], 'total_pages' => 1, 'total_results' => 1];
        }

        if (preg_match('/^tt\d+$/', $query)) {
            $result = $this->find_by_id($query, 'imdb_id');
            if (is_wp_error($result)) return $result;
            $tv = $result['tv_results'][0] ?? null;
            if (!$tv) return new \WP_Error('no_results', esc_html__('No TV show found with this IMDb ID.', 'cine-movie-engine'));
            return ['page' => 1, 'results' => [$tv], 'total_pages' => 1, 'total_results' => 1];
        }

        if (preg_match('/^(.*?)\s*\((\d{4})\)$/', $query, $matches)) {
            $args['query'] = $matches[1];
            $args['first_air_date_year'] = $matches[2];
        } else {
            $args['query'] = $query;
        }

        $url = add_query_arg($args, $this->base_url . 'search/tv');
        return $this->make_request($url);
    }

    public function get_movie_details($movie_id) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key'         => $this->api_key,
            'append_to_response' => 'credits,videos,external_ids',
        ], $this->base_url . 'movie/' . $movie_id);

        return $this->make_request($url);
    }

    public function get_tv_details($tv_id) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key'         => $this->api_key,
            'append_to_response' => 'credits,videos,external_ids,content_ratings',
        ], $this->base_url . 'tv/' . $tv_id);

        return $this->make_request($url);
    }

    public function search_person($query, $page = 1) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        if (is_numeric($query)) {
            $details = $this->get_person_details($query);
            if (is_wp_error($details)) return $details;
            return ['page' => 1, 'results' => [$details], 'total_pages' => 1, 'total_results' => 1];
        }

        $args = [
            'api_key' => $this->api_key,
            'query'   => $query,
            'page'    => $page,
        ];

        $url = add_query_arg($args, $this->base_url . 'search/person');
        return $this->make_request($url);
    }

    public function get_person_details($person_id) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key'            => $this->api_key,
            'append_to_response' => 'external_ids',
        ], $this->base_url . 'person/' . $person_id);

        return $this->make_request($url);
    }

    public function get_season_details($tv_id, $season_number) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key' => $this->api_key,
        ], $this->base_url . 'tv/' . $tv_id . '/season/' . $season_number);

        return $this->make_request($url);
    }

    public function get_episode_details($tv_id, $season_number, $episode_number) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key' => $this->api_key,
        ], $this->base_url . 'tv/' . $tv_id . '/season/' . $season_number . '/episode/' . $episode_number);

        return $this->make_request($url);
    }

    public function get_tv_season_details($tv_id, $season_number) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key' => $this->api_key,
            'language' => 'en-US',
        ], $this->base_url . "tv/{$tv_id}/season/{$season_number}");

        return $this->make_request($url);
    }

    public function get_tv_episode_details($tv_id, $season_number, $episode_number) {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key' => $this->api_key,
            'language' => 'en-US',
        ], $this->base_url . "tv/{$tv_id}/season/{$season_number}/episode/{$episode_number}");

        return $this->make_request($url);
    }

    public function get_popular_movies($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'movie/popular'));
    }

    public function get_trending_movies($time_window = 'day', $page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'trending/movie/' . $time_window));
    }

    public function get_now_playing_movies($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'movie/now_playing'));
    }

    public function get_upcoming_movies($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'movie/upcoming'));
    }

    public function get_top_rated_movies($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'movie/top_rated'));
    }

    public function get_popular_tv($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'tv/popular'));
    }

    public function get_trending_tv($time_window = 'day', $page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'trending/tv/' . $time_window));
    }

    public function get_top_rated_tv($page = 1) {
        return $this->make_request(add_query_arg(['api_key' => $this->api_key, 'page' => $page], $this->base_url . 'tv/top_rated'));
    }

    public function find_by_id($external_id, $source = 'imdb_id') {
        if (empty($this->api_key)) {
            return new \WP_Error('missing_api_key', esc_html__('TMDb API Key is missing.', 'cine-movie-engine'));
        }

        $url = add_query_arg([
            'api_key'        => $this->api_key,
            'external_source' => $source,
        ], $this->base_url . 'find/' . $external_id);

        return $this->make_request($url);
    }

    public function download_image($path, $post_id, $type = 'poster') {
        if (empty($path)) {
            return false;
        }

        $size = ($type === 'poster') ? 'w500' : 'w185';
        $image_url = 'https://image.tmdb.org/t/p/' . $size . $path;

        if (apply_filters('movie_engine_bulk_import_skip_images', false)) {
            update_post_meta($post_id, '_movie_engine_pending_img_' . $type, $image_url);
            return $image_url;
        }

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

        $tmp = download_url($image_url);

        if (is_wp_error($tmp)) {
            return false;
        }

        $file_array = [
            'name'     => basename($path),
            'tmp_name' => $tmp,
        ];

        $id = media_handle_sideload($file_array, $post_id, $type . ' image');

        if (is_wp_error($id)) {
            wp_delete_file($file_array['tmp_name']);
            return false;
        }

        return $id;
    }

    private function make_request($url) {
        $url = esc_url_raw($url);
        $cache_key = 'tmdb_api_' . md5($url);
        $cached_data = \MovieEngine\Core\Cache::get($cache_key);

        if ($cached_data !== false) {
            return $cached_data;
        }

        $response = wp_remote_get($url, [
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return $response;
        }

        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return new \WP_Error('json_error', esc_html__('Failed to parse TMDb response.', 'cine-movie-engine'));
        }

        if (isset($data['status_message']) && isset($data['success']) && $data['success'] === false) {
            return new \WP_Error('tmdb_error', $data['status_message']);
        }

        $expiration = strpos($url, '/search/') !== false ? HOUR_IN_SECONDS : DAY_IN_SECONDS;
        \MovieEngine\Core\Cache::set($cache_key, $data, $expiration);

        return $data;
    }
}
