<?php

namespace App\Console\Commands\Update;

use App\Models\Crontjob;
use App\Models\Track;
use App\Models\TrackArtist;
use App\Models\TrackUser;
use App\Repositories\TrackRepository;
use App\User;
use Carbon\Carbon;
use Illuminate\Console\Command;

class UpdateTrackArtistCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'track:update-artist {src?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Cập nhật thông tin ca sĩ, nhạc sĩ của bài hát.';

    protected $trackRepository;

    /**
     * Create a new command instance.
     *
     * UpdateTrackArtistCommand constructor.
     * @param TrackRepository $trackRepository
     */
    public function __construct(TrackRepository $trackRepository)
    {
        parent::__construct();
        ini_set('max_execution_time', -1);
        $this->trackRepository = $trackRepository;
    }

    /**
     * Cập nhật thông tin ca sĩ cho bài hát theo từng hệ thống: zing, nct, keeng
     *
     * B1: Lấy thông tin ca sĩ về
     * B2: Check trong bảng users xem đã có chưa, có thì lấy ID, chưa có thì tạo và lấy ID
     * B3: Check trong bảng track_user:
     * - Check cặp (track_id, name): nếu tồn tại thì update user_id, nếu chưa thì insert (track_id, user_id, name)
     * - Check cặp (track_id, user_id): nếu có thì thôi, nếu chưa thì insert (track_id, usser_id, name)
     *
     * @return mixed
     */
    public function handle()
    {
        $src = $this->argument('src');

        if (empty($src) || !in_array($src, ['zing', 'nct', 'keeng', 'all'])) {
            $src = $this->choice('Chọn nguồn cập nhật ', ['zing', 'nct', 'keeng', 'all']);
        }

        // Ghi log
        Crontjob::create(['message' => 'UpdateTrackArtistCommand is called (' . $src . ')']);

        echo "\n Bắt đầu cập nhật ca sĩ cho bài hát.";

        switch ($src) {
            case 'zing':
                $track_id = [];
                $track_id_singer = [];
                // Lấy playlist ----------------------------------------------------------------------------------------
                $url = config('api.zing.chart_realtime');
                $curl = curlZingMp3($url);
                $data = json_decode($curl);
                $tracks = $data->data->items;
                if ($tracks) {
                    foreach ($tracks as $key => $track) {
                        if (isset($track->title) && isset($track->artists_names) && !empty($track->artists_names)) {
                            $track_id[] = $track->id;
                            $track_id_singer[$track->id] = $track->artists_names;
                        }
                    }
                }
                // Xử lý cập nhật
                /*if (count($track_id_singer) > 0) {
                    $track_db = Track::select(['id', 'id_zing', 'id_nct', 'id_keeng', 'title'])
                        ->whereIn('id_zing', $track_id)
                        ->get();

                    $this->privateUpdateTrackSinger($src, $track_db, $track_id_singer);
                }*/

                // Lấy bài mới xuất bản --------------------------------------------------------------------------------
                $track_id = [];
                $track_id_singer = [];

                $url_new_release = config('api.zing.new_release');
                $curl_new_release = curlZingMp3($url_new_release);
                $data_new_release = json_decode($curl_new_release);
                $tracks_new_release = $data_new_release->data->items;

                if ($tracks_new_release) {
                    foreach ($tracks_new_release as $key => $track) {
                        if (isset($track->title) && isset($track->artists_names) && !empty($track->artists_names)) {
                            $track_id[] = $track->id;
                            $track_id_singer[$track->id] = $track->artists_names;
                        }

                    }
                }
                // Xử lý cập nhật
                /*if (count($track_id_singer) > 0) {
                    $track_db = Track::select(['id', 'id_zing', 'id_nct', 'id_keeng', 'title'])
                        ->whereIn('id_zing', $track_id)
                        ->get();

                    $this->privateUpdateTrackSinger($src, $track_db, $track_id_singer);
                }*/

                // Xử lý cập nhật nhạc sĩ ------------------------------------------------------------------------------
                echo "\n Bắt đầu cập nhật Nhạc sĩ cho bài hát.";
                $array_zing_track = Track::select(['id', 'id_zing', 'singer_list', 'composer_list'])
                    ->whereNotNull('id_zing')
                    ->where('id_zing', '<>', '')
                    ->whereNull('composer_list')
                    ->take(10)
                    ->get();

                if ($array_zing_track) {
                    $track_id_composer = [];
                    foreach ($array_zing_track as $key => $track) {
                        $url = getZingSongInfoUrl($track->id_zing);
                        $composer_list = $this->privateGetZingSongInfo($url);
                        if ($composer_list) {
                            $track_id_composer[$track->id] = $composer_list;
                        }
                    }
                    if (count($track_id_composer) > 0) {
                        $this->privateUpdateTrackSinger($src, $array_zing_track, [], $track_id_composer);
                    }
                }
                echo "\n Kết thúc cập nhật Nhạc sĩ cho bài hát.";

                break;
            case 'nct':
                $track_id = [];
                $track_id_singer = [];
                // Xử lý cập nhật ca sĩ --------------------------------------------------------------------------------
                $url = config('api.nct.top100');
                $url_playlist_top100 = config('api.nct.playlist_top100');
                $tracks = $this->trackRepository->processNctGetTrackInfoFromTop100($url);
                if ($tracks) {
                    foreach ($tracks as $key => $track) {
                        if (isset($track['title']) && isset($track['singer'])) {
                            $track_id[] = $track['id_nct'];
                            $track_id_singer[$track['id_nct']] = $track['singer'];
                        }
                    }
                }

                if (count($track_id_singer) > 0) {
                    $track_db = Track::select(['id', 'id_zing', 'id_nct', 'id_keeng', 'title'])
                        ->whereIn('id_nct', $track_id)
                        ->get();

                    $this->privateUpdateTrackSinger($src, $track_db, $track_id_singer);
                }

                // Xử lý cập nhật nhạc sĩ ------------------------------------------------------------------------------
                $tracks_nct = $this->trackRepository->getTrackBySource($src, null, 100, true);
                $track_id_composer = $this->trackRepository->getComposerBySource($src, $tracks_nct);
                if (count($track_id_composer) > 0) {
                    $this->privateUpdateTrackSinger($src, $tracks_nct, [], $track_id_composer);
                } else {
                    echo "\n - Thông tin Nhạc sĩ đã cập nhật đầy đủ trước đó.";
                }

                break;
            case 'keeng':
                $track_id = [];
                $track_id_singer = [];
                $track_id_composer = [];
                //
                $url = getKeengUrlNewRealease(1, 500);
                $curl = cURL($url);
                $data = json_decode($curl);
                $tracks = $data->data;
                if ($tracks) {
                    foreach ($tracks as $key => $track) {
                        if (isset($track->identify) && isset($track->singer) && !empty($track->singer)) {
                            $track_id[] = $track->identify;
                            $track_id_singer[$track->identify] = $track->singer;
                            $composer = (isset($track->info_extra) && isset($track->info_extra->author_name)) ? $track->info_extra->author_name : '?';
                            $track_id_composer[$track->identify] = $composer;
                        }
                    }
                }
                // Xử lý cập nhật
                if (count($track_id_singer) > 0) {
                    $track_db = Track::select(['id', 'id_zing', 'id_nct', 'id_keeng', 'title'])
                        ->whereIn('id_keeng', $track_id)
                        ->get();

                    $this->privateUpdateTrackSinger($src, $track_db, $track_id_singer, $track_id_composer);
                }
                break;
            case 'all': break;
            default:
        }

        echo "\n Kết thúc cập nhật ca sĩ cho bài hát. \n";
    }

    /**
     * Hàm xử lý đồng bộ thông tin nghệ sĩ ở bảng users và track_user, track_artists
     *
     * @param $src
     * @param $track_db
     * @param array $track_id_singer
     * @param array $track_id_composer
     *
     * @return bool
     */
    private function privateUpdateTrackSinger($src, $track_db, $track_id_singer=[], $track_id_composer=[])
    {
        echo "\n Cập nhật cho tổng số bài: " . $track_db->count();

        foreach ($track_db as $key => $track) {
            switch ($src) {
                case 'zing': $src_track_id = $track->id_zing; break;
                case 'nct': $src_track_id = $track->id_nct; break;
                case 'keeng': $src_track_id = $track->id_keeng; break;
                default: return false;
            }

            if (count($track_id_singer) > 0 && array_key_exists($src_track_id, $track_id_singer)) {
                $user = User::updateOrCreate(
                    ['full_name' => $track_id_singer[$src_track_id]],
                    ['user_type' => 2, 'updated_at' => Carbon::now()]
                );

                TrackUser::updateOrCreate(
                    [
                        'track_id' => $track->id,
                        'user_id' => $user->id
                    ],
                    ['name' => $track_id_singer[$src_track_id]]
                );

                echo "\n - Cập nhật xong Ca sĩ (ID: " . (isset($user->id) ? $user->id : '') . ") cho bài hát (ID: " . (isset($track->id) ? $track->id : '') . ").";
            }

            // Cập nhật sáng tác
            if (count($track_id_composer) > 0 && array_key_exists($track->id, $track_id_composer)) {
                $user = User::updateOrCreate(
                    ['full_name' => $track_id_composer[$track->id]],
                    ['user_type' => 2, 'updated_at' => Carbon::now()]
                );

                TrackArtist::updateOrCreate(
                    [
                        'track_id' => $track->id,
                        'user_id' => $user->id
                    ],
                    ['name' => $track_id_composer[$track->id]]
                );

                echo "\n - Cập nhật xong Nhạc sĩ (ID: " . (isset($user->id) ? $user->id : '') . ") cho bài hát (ID: " . (isset($track->id) ? $track->id : '') . ").";
            }
        }
    }

    /**
     * Hàm gọi api thông tin bài hát để lấy tên nhạc sĩ
     *
     * @param $api_url
     * @return null|string
     */
    private function privateGetZingSongInfo($api_url)
    {
        $composer_name = [];

        if ($api_url) {
            $curl = curlZingMp3($api_url);
            if ($curl) {
                $response = json_decode($curl);
                if (isset($response->err) && $response->err == 0) {
                    $data = $response->data;
                    echo "\n - Đang xử lý lấy nhạc sĩ của bài hát: " . $data->title;
                    if (isset($data->composers)) {
                        $composers = $data->composers;
                        foreach ($composers as $key => $composer) {
                            $composer_name[] = $composer->name;
                        }
                    }
                }
            }
        }

        if (count($composer_name) > 0) {
            return implode(', ', $composer_name);
        }

        return null;
    }
}