<?php

namespace App\Repositories\Admin;

use App\Models\Category;
use App\Models\Config;
use App\Models\Country;
use App\Models\Genre;
use App\Models\Movie;
use App\Models\MovieLanguage;
use App\Models\Star;
use App\Models\TvShow;
use App\Models\VideoQuality;
use App\Repositories\Interfaces\Admin\ImporterInterface;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Tmdb\Laravel\Facades\Tmdb;

class ImporterRepository implements ImporterInterface
{

    public function getMovieDetails($movie_id, $data = null)
    {
        $apiKey = Config::where('title', 'tmdb_api_key')->value('value');
        $url = "https://api.themoviedb.org/3/movie/" . $movie_id . "?api_key={$apiKey}&append_to_response=credits,release_dates";
        $response = Http::withOptions(['verify' => false,])->timeout(60)->get($url);
        $movieDetails = $response->json();
        if ($data) {
            return $movieDetails[$data];
        } else {
            return $movieDetails;
        }
    }


    public function getTvShowDetails($show_id, $data = null)
    {
        $apiKey = Config::where('title', 'tmdb_api_key')->value('value');
        $url = "https://api.themoviedb.org/3/tv/" . $show_id . "?api_key={$apiKey}&append_to_response=credits,release_dates";
        $response = Http::withOptions(['verify' => false,])->timeout(60)->get($url);
        $movieDetails = $response->json();
        if ($data) {
            return $movieDetails[$data];
        } else {
            return $movieDetails;
        }
    }
    public function importFromTMDB($language, $type, $id)
    {
        if (in_array($type, [
            'movies_by_title',
            'popular_movies',
            'top_rated_movies',
            'upcoming_movies',
            'movies_by_year',
            'movies_by_genre',
            'movies_by_keyword',
            'movies_by_people',
        ])) {
            $type = 'movie';
            $details = $this->getMovieDetails($id);

            $genres_ids = $this->insertGenres($details['genres']);
            $country_ids = $this->insertCountries($details['production_countries']);
            $languages_ids = $this->insertLanguages($details['spoken_languages']);
            $actor_ids = $this->insertActors($details['credits']['cast']);
            $director_ids = $this->insertDirectors($details['credits']['crew']);
            $writer_ids = $this->insertWriters($details['credits']['crew']);
            $trailers = '';

            $formatted_keywords = '';
            $formatted_response = $this->TMDBDataFormatForSingleData($this->getMovieDetails($id));

            $this->storeMovieToDBFromTMDB(
                $formatted_response,
                $type,
                $actor_ids,
                $director_ids,
                $writer_ids,
                $country_ids,
                $genres_ids,
                $languages_ids,
                $trailers,
                $formatted_keywords
            );
            return true;
        }
        if (in_array($type, [
            'tvshows_by_title',
            'popular_tvshows',
            'top_rated_tvshows',
            'on_air_tvshows',
            'tvshows_by_year',
            'tvshows_latest',
            'tvshows_by_people',
        ])) {
            $type = 'tv_show';
            // dd($this->getTvShowDetails($id));
            $details = $this->getTvShowDetails($id);

            $genres_ids = $this->insertGenres($details['genres']);
            $country_ids = $this->insertCountries($details['production_countries']);
            $languages_ids = $this->insertLanguages($details['spoken_languages']);
            $actor_ids = $this->insertActors($details['credits']['cast']);
            $director_ids = $this->insertDirectors($details['credits']['crew']);
            $writer_ids = $this->insertWriters($details['credits']['crew']);

            $trailers = '';

            $formatted_keywords = '';
            $formatted_response = $this->TMDBDataFormatForSingleData($this->getTvShowDetails($id), 'tv_show');

            $this->storeMovieToDBFromTMDB(
                $formatted_response,
                $type,
                $actor_ids,
                $director_ids,
                $writer_ids,
                $country_ids,
                $genres_ids,
                $languages_ids,
                $trailers,
                $formatted_keywords
            );
            return true;
        }
    }
    private function insertGenres($genres)
    {
        $ids = [];
        foreach ($genres as $value):
            $genre = Genre::where('name', $value['name'])->first();
            if (!$genre):
                $genre = new Genre();
                $genre->name = $value['name'];
                $genre->slug = Str::slug($value['name']);
                $genre->save();
                $ids[] = json_encode($genre->id);
            else:
                $ids[] = json_encode($genre->id);
            endif;
        endforeach;
        return $ids;
    }
    private function insertCountries($contries)
    {
        $ids = [];
        foreach ($contries as $value):
            $country = Country::where('name', $value['name'])->first();
            if (!$country):
                $country = new Country();
                $country->name = $value['name'];
                $country->slug = Str::slug($value['name']);
                $country->save();
                $ids[] = json_encode($country->id);
            else:
                $ids[] = json_encode($country->id);
            endif;
        endforeach;
        return $ids;
    }
    private function insertLanguages($languages)
    {
        $ids = [];
        foreach ($languages as $value):
            $language = MovieLanguage::where('name', $value['english_name'])->first();
            if (!$language):
                $language = new MovieLanguage();
                $language->name = $value['english_name'];
                $language->slug = Str::slug($value['english_name']);
                $language->save();
                $ids[] = json_encode($language->id);
            else:
                $ids[] = json_encode($language->id);
            endif;
        endforeach;
        return $ids;
    }
    private function insertActors($casts)
    {
        $ids = [];
        foreach ($casts as $value):
            if ($value['known_for_department'] == 'Acting') {
                $star = Star::where('star_type', 'actor')->where('star_name', $value['name'])->first();
                if (!$star):
                    $star = new Star();
                    $star->star_name = $value['name'];
                    $star->slug = Str::slug($value['name']);
                    $star->star_type = $value['known_for_department'] == 'Acting' ? 'actor' : '';
                    $star->star_image = json_encode(['original_image' => TMDBImageUrl($value['profile_path'], 'w154')]);
                    $star->save();
                    $ids[] = json_encode($star->id);
                else:
                    $ids[] = json_encode($star?->id);
                endif;
            }
        endforeach;
        return $ids;
    }
    private function insertDirectors($casts)
    {
        $ids = [];
        foreach ($casts as $value):
            if ($value['known_for_department'] == 'Directing' || $value['known_for_department'] == 'Art') {
                $star = Star::where('star_type', 'director')->where('star_name', $value['name'])->first();
                if (!$star):
                    $star = new Star();
                    $star->star_name = $value['name'];
                    $star->slug = Str::slug($value['name']);
                    $star->star_type = $value['known_for_department'] == 'Directing' ? 'director' : ($value['known_for_department'] == 'Art' ? 'director' : '');
                    $star->star_image = json_encode(['original_image' => TMDBImageUrl($value['profile_path'], 'w154')]);
                    $star->save();
                    $ids[] = json_encode($star->id);
                else:
                    $ids[] = json_encode($star?->id);
                endif;
            }
        endforeach;
        return $ids;
    }
    private function insertWriters($casts)
    {
        $ids = [];
        foreach ($casts as $value):
            if ($value['known_for_department'] == 'Writing') {
                $star = Star::where('star_type', 'writer')->where('star_name', $value['name'])->first();
                if (!$star):
                    $star = new Star();
                    $star->star_name = $value['name'];
                    $star->slug = Str::slug($value['name']);
                    $star->star_type = $value['known_for_department'] == 'Writing' ? 'writer' : '';
                    $star->star_image = $value['profile_path'];
                    $star->save();
                    $ids[] = json_encode($star->id);
                else:
                    $ids[] = json_encode($star?->id);
                endif;
            }
        endforeach;
        return $ids;
    }

    private function storeMovieToDBFromTMDB(
        $movie_response,
        $type,
        $actor_ids,
        $director_ids,
        $writer_ids,
        $country_ids,
        $genres_ids,
        $languages_ids,
        $trailers,
        $formatted_keywords = ''
    ) {

        if ($type == 'tv_show') {
            $video = new TvShow();
        } else {
            $video = new Movie();
        }

        $video->tmdb_id = $movie_response['id'];
        $video->imdbid = $movie_response['id'];
        $video->title = $movie_response['name'];
        $video->slug = Str::slug($movie_response['name']);
        $video->description = $movie_response['overview'];
        $video->stars = json_encode($actor_ids);
        $video->director = json_encode($director_ids);
        $video->writer = json_encode($writer_ids);
        $video->rating = isset($movie_response['imdb_rating']) ? $movie_response['imdb_rating'] : null;
        $video->release = $movie_response['release_date'];
        $video->country = json_encode($country_ids);
        $video->genre = json_encode($genres_ids);
        $video->language = json_encode($languages_ids);
        $video->runtime = $movie_response['runtime'];
        $video->description = $movie_response['overview'];
        $video->imdb_rating = $movie_response['vote_average'];
        $video->video_type = Category::first()->id;
        $video->video_quality = VideoQuality::first()->id;

        $video->status = 1;
        $video->enable_download = 1;
        $video->is_free = 1;
        $video->is_tvseries = $type == 'tv_show' ? 1 : 0;

        $trailer_url = $type == 'movie' ?
            (isset($trailers['youtube'][0]['source']) ? "https://www.youtube.com/watch?v=" . $trailers['youtube'][0]['source'] : null) : (isset($trailers['results'][0]['key']) ? "https://www.youtube.com/watch?v=" . $trailers['results'][0]['key'] : null);

        $video->trailler_youtube_source = $trailer_url;
        $video->trailer = $trailer_url != '' ? 1 : 0;
        $video->seo_title = $movie_response['name'];
        $video->meta_description = $movie_response['overview'];
        $video->focus_keyword = $formatted_keywords;
        $video->tags = $formatted_keywords;
        $video->thumbnail = json_encode(['original_image' => TMDBImageUrl($movie_response['poster_path'], 'w342')]);
        $video->poster = json_encode(['original_image' => TMDBImageUrl($movie_response['backdrop_path'], 'w500')]);
        $video->save();
    }

    private function TMDBDataFormatForSingleData($response, $type = 'movie')
    {

        if ($type == 'tv_show'):

            $formatted_obj['id'] = @$response['id'];
            $formatted_obj['name'] = @$response['name'];
            $formatted_obj['origin_country'] = @$response['origin_country'];
            $formatted_obj['original_language'] = @$response['original_language'];
            $formatted_obj['original_name'] = @$response['original_name'];
            $formatted_obj['overview'] = @$response['overview'];
            $formatted_obj['popularity'] = @$response['popularity'];
            $formatted_obj['release_date'] = @$response['first_air_date'];
            $formatted_obj['vote_average'] = @$response['vote_average'];
            $formatted_obj['vote_count'] = @$response['vote_count'];
            $formatted_obj['backdrop_path'] = @$response['backdrop_path'];
            $formatted_obj['poster_path'] = @$response['poster_path'];
            $formatted_obj['runtime'] = @$response['runtime'];
            $formatted_obj['type'] = 'tv_show';

            return $formatted_obj;

        elseif ($type == 'movie'):

            $formatted_obj['id'] = @$response['id'];
            $formatted_obj['name'] = @$response['title'];
            $formatted_obj['imdb_id'] = @$response['imdb_id'];
            $formatted_obj['origin_country'] = @$response['original_language'];
            $formatted_obj['original_language'] = @$response['original_language'];
            $formatted_obj['original_name'] = @$response['original_title'];
            $formatted_obj['overview'] = @$response['overview'];
            $formatted_obj['popularity'] = @$response['popularity'];
            $formatted_obj['release_date'] = @$response['release_date'];
            $formatted_obj['vote_average'] = @$response['vote_average'];
            $formatted_obj['vote_count'] = @$response['vote_count'];
            $formatted_obj['backdrop_path'] = @$response['backdrop_path'];
            $formatted_obj['poster_path'] = @$response['poster_path'];
            $formatted_obj['runtime'] = @$response['runtime'];
            $formatted_obj['type'] = 'movie';

            return $formatted_obj;
        endif;
    }


    public function getTMDBData($request)
    {
        $apiKey = Config::where('title', 'tmdb_api_key')->value('value');
        $language = $request['language'] ?? 'en';
        $type = $request['type'];
        $query = $request['title'] ?? null;
        $tmdb_id = $request['tmdb_id'] ?? null;
        $year = $request['year'] ?? null;
        $page = $request['page'] ?? 1;

        $params = [
            'api_key' => $apiKey,
            'language' => $language,
            'page' => $page,
            'query' => $query,
        ];

        switch ($type) {
            case 'movies_by_title':
            case 'tvshows_by_title':
                $url = $type === 'movies_by_title' ? 'https://api.themoviedb.org/3/search/movie' : 'https://api.themoviedb.org/3/search/tv';
                $params['query'] = $query;
                break;

            case 'movies_by_year':
                $url = 'https://api.themoviedb.org/3/discover/movie';
                $params['year'] = $year;
                break;

            case 'tvshows_by_year':
                $url = 'https://api.themoviedb.org/3/discover/tv';
                $params['year'] = $year;
                break;

            case 'movies_by_genre':
                $url = 'https://api.themoviedb.org/3/discover/movie';
                $params['with_genres'] = $tmdb_id;
                break;

            case 'movies_by_keyword':
                $url = 'https://api.themoviedb.org/3/search/movie';
                $params['query'] = $query;
                break;
            case 'movies_by_people':
                $url = 'https://api.themoviedb.org/3/person/popular';
                $params['query'] = $query;
                break;

            case 'tvshows_by_people':
                $url = 'https://api.themoviedb.org/3/person/popular';
                $params['query'] = $query;
                break;

            case 'popular_movies':
            case 'top_rated_movies':
            case 'upcoming_movies':
                $endpoint = str_replace('_movies', '', $type);
                $url = "https://api.themoviedb.org/3/movie/$endpoint";
                break;

            case 'tvshows_latest':
                $url = 'https://api.themoviedb.org/3/tv/popular';
                break;

            case 'popular_tvshows':
            case 'top_rated_tvshows':
                $endpoint = str_replace('_tvshows', '', $type);
                $url = in_array($endpoint, ['latest', 'on_air'])
                    ? "https://api.themoviedb.org/3/tv/$endpoint"
                    : "https://api.themoviedb.org/3/tv/$endpoint";
                break;
            case 'on_air_tvshows':
                $url = "https://api.themoviedb.org/3/tv/on_the_air";
                break;

            default:
                throw new \Exception('Invalid type');
        }

        $response = Http::withOptions(['verify' => false])->get($url, $params);

        return $response->json();
    }
}
