<?php

namespace CCDN\Controllers;

use CCDN\Helpers\Api\ApiHandler;
use CCDN\Helpers\Api\Response\Field\SerialStatus;
use CCDN\Helpers\Api\Response\FranchiseDetailsInterface;
use CCDN\Helpers\Api\Response\ListInterface;
use CCDN\Helpers\Api\Response\ListResponse;
use CCDN\Helpers\Api\ResponseFactory;
use CCDN\Helpers\CCDNUploadPoster;
use CCDN\Helpers\Controller;
use CCDN\Helpers\Entities\Post;
use CCDN\Helpers\Facade\DB\Model as ModelStatic;
use CCDN\Helpers\Facade\Http\Response;
use CCDN\Helpers\Facade\Http\Url;
use CCDN\Helpers\Http\Request;
use CCDN\Helpers\Modules\Module\PatterParser;
use CCDN\Helpers\NotSeasonsFranchiseAltUrl;
use CCDN\Helpers\NotSeasonsFranchiseMetaTitle;
use CCDN\Helpers\NotSeasonsFranchiseTitle;
use CCDN\Helpers\PostCategories;
use CCDN\Helpers\SeasonsFranchiseAltUrl;
use CCDN\Helpers\SeasonsFranchiseMetaTitle;
use CCDN\Helpers\SeasonsFranchiseTitle;
use CCDN\Helpers\Settings;
use Exception;
use GuzzleHttp\Promise;
use GuzzleHttp\Psr7\Response as GuzzleResponse;
use URLify;

class ParseDataBaseController extends Controller
{
    protected $viewsFolder = 'parse-database';
    protected $parent = '';

    public function __construct($parent = 'parse-database')
    {
        $this->parent = $parent;
    }

    public function main()
    {

        $api = new ApiHandler();

        $genres = $api->getGenres([
            'limit' => 500
        ])->getBody();


        $country = $api->getCountry([
            'limit' => 500
        ])->getBody();

        return Response::make($this->render('main', [
            'genres' => ResponseFactory::createGenre($genres),
            'countries' => ResponseFactory::createCountry($country),
            'serialStatus' => new SerialStatus(),
        ]));
    }

    public function getCollapsList(Request $request)
    {

        $search = $request->get('search');
        $draw = $request->get('draw');
        $start = $request->get('start');
        $length = $request->get('length');
        $franchiseType = $request->get('franchise_type');
        $order = $request->get('order')[0];
        $kinopoiskIdField = Settings::get('kinopoisk_id_field');
        $ccdnIdField = Settings::get('ccdn_id_field');

        $whereIn = [];
        $promises = [];

        try {

            $api = new ApiHandler();

            $fields = [
                '4' => 'kinopoisk',
                '5' => 'imdb',
                '6' => 'year',
            ];

            $sortField = $fields[$order['column']];
            $sortType = $order['dir'] === 'desc' ? '-' : '';

            $response = $api->getList([
                'type' => $franchiseType,
                'limit' => $length,
                'page' => floor((($start + 1) / $length) + 1),
                'name' => $search['value'],
                'sort' => $sortType . $sortField,
            ])->getBody();

            $response = ResponseFactory::createListResponse($response);

            if ($response === null) {
                return Response::json([
                    'draw' => $draw,
                    'recordsTotal' => 0,
                    'recordsFiltered' => 0,
                    'data' => [],
                ]);
            }

            /** @var ListInterface $item */
            foreach ($response['results'] as $item) {
                $id = $item->getId();

                $whereIn['collaps_id'][] = $id;

                if (($kp_id = $item->getKinopoiskId()) !== null) {
                    $whereIn['kinopoisk_id'][] = $kp_id;
                }

                $promises[$id] = $api->getFranchiseDetailsAsync([
                    'id' => $id
                ]);

            }

            $response['results'] = [];
            $waitPromises = Promise\settle($promises)->wait();

            foreach ($promises as $key => $promise) {
                $promise = $waitPromises[$key];
                if ($promise['state'] === 'rejected') {
                    continue;
                }
                /**
                 * @var GuzzleResponse $promise
                 */
                $promise = $promise['value'];
                if ($promise->getStatusCode() !== 200) {
                    continue;
                }
                $response['results'][] = ResponseFactory::createFranchiseDetail(json_decode($promise->getBody()->getContents(),
                    true));
            }

            $whereIn['collaps_id'] = implode(',', $whereIn['collaps_id']);
            $whereIn['kinopoisk_id'] = implode(',', $whereIn['kinopoisk_id']);

            $dbPrefix = ModelStatic::getPrefix();

            $query = "SELECT * FROM (SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(xfields, '{$ccdnIdField}|', -1), '|', 1) AS collaps_id";

            if ($kinopoiskIdField) {
                $query .= ", SUBSTRING_INDEX(SUBSTRING_INDEX(xfields, '{$kinopoiskIdField}|', -1), '|', 1) AS kinopoisk_id";
            }

            $query .= " FROM `{$dbPrefix}_post`) as t WHERE t.collaps_id IN ({$whereIn['collaps_id']})";
            if ($kinopoiskIdField && $whereIn['kinopoisk_id']) {
                $query .= " OR t.kinopoisk_id IN ({$whereIn['kinopoisk_id']})";
            }
            $queryResult = ModelStatic::select($query, true);

            $results = [];

            /** @var FranchiseDetailsInterface $item */
            foreach ($response['results'] as $key => $item) {
                $collaps_id = (int)$item->getId();
                $kp_id = $item->getKinopoiskId();

                $results[$key] = [
                    'id' => $collaps_id,
                    'name' => $item->getName(),
                    'quality' => $item->getQuality(),
                    'kinopoiskRating' => $item->getKinopoiskRating(),
                    'ImdbRating' => $item->getImdbRating(),
                    'year' => $item->getYear(),
                    'kinopoisk_id' => $kp_id,
                    'ads' => $item->getAds(),
                    'has_in_db' => false,
                    'post_url' => null,
                ];

                foreach ($queryResult as $postItem) {
                    if ($kinopoiskIdField && $kp_id !== null && (string)$postItem['kinopoisk_id'] !== $kp_id) {
                        continue;
                    }

                    if ((int)$postItem['collaps_id'] !== $collaps_id)
                        continue;

                    $results[$key]['has_in_db'] = true;
                    $results[$key]['post_url'] = Url::toAdminPanel() . "?mod=editnews&action=editnews&id={$postItem['id']}";
                    break;
                }
            }

            $data = [
                'draw' => $draw,
                'recordsTotal' => $response['total'],
                'recordsFiltered' => $response['total'],
                'data' => $results,
            ];
        } catch (Exception $e) {
            $data = [
                'draw' => $draw,
                'recordsTotal' => 0,
                'recordsFiltered' => 0,
                'data' => [],
                'error' => $e->getMessage(),
            ];

        }
        return Response::json($data);
    }

    public function parse(Request $request)
    {
        $item = json_decode($request->post('item'), true);
        $listItem = new ListResponse($item);
        $ccdnConf = Settings::all();

        $dbPrefix = ModelStatic::getPrefix();

        if (($KpID = $listItem->getKinopoiskId()) !== null) {
            $xfield = [
                'key' => $ccdnConf->kinopoisk_id_field,
                'value' => $KpID
            ];
        } else {
            $xfield = [
                'key' => $ccdnConf->ccdn_id_field,
                'value' => $listItem->getId()
            ];
        }

        $query = "SELECT * FROM (SELECT id,SUBSTRING_INDEX(SUBSTRING_INDEX(xfields,";
        $query .= "'{$xfield['key']}|', -1), '|', 1) AS sid FROM `{$dbPrefix}_post`) as t WHERE t.sid = {$xfield['value']}";

        if ($rawPost = ModelStatic::select($query)) {
            return Response::json([
                'message' => "Post exist, post id: {$rawPost['id']}",
            ], 400);
        }

        $api = new ApiHandler();

        $response = $api->getFranchiseDetails([
            'id' => $listItem->getId()
        ]);

        if ($response === null) {
            return Response::json([
                'message' => "Not found. Collaps id: {$listItem->getId()}",
            ], 404);
        }


        $genreFilter = json_decode($request->post('genreFilter'), true);
        $countryFilter = json_decode($request->post('countryFilter'), true);
        $franchiseStatus = $request->post('franchiseStatus');
        if ($franchiseStatus !== null && !$response->getSerialStatus()->is($franchiseStatus)) {
            return Response::json([
                'message' => "Season franchise is not : {$franchiseStatus}",
                'item_status' => $response->getSerialStatus()->get()
            ], 400);
        }

        if (!empty($genreFilter)) {
            $responseGenres = $response->getGenres()->getData();
            $genreFilterCondition = true;
            foreach ($responseGenres as $value) {
                if (in_array($value, $genreFilter, true)) {
                    $genreFilterCondition = false;
                    break;
                }
            }

            if ($genreFilterCondition) {
                return Response::json([
                    'message' => 'Genres filter',
                    'item_id' => $response->getId(),
                ], 400);
            }
        }

        if (!empty($countryFilter)) {
            $responseCountries = $response->getCountries()->getData();
            $countryFilterCondition = true;
            foreach ($responseCountries as $value) {
                if (in_array($value, $countryFilter, true)) {
                    $countryFilterCondition = false;
                    break;
                }
            }

            if ($countryFilterCondition) {
                return Response::json([
                    'message' => 'Countries filter',
                    'item_id' => $response->getId(),
                ], 400);
            }
        }


        $season = '';
        $episode = '';

        $seasonsNumber = $response->getSeasons()->getLast()->getNumber();
        $episodesNumber = $response->getSeasons()->getLast()->getEpisodes()->getLast()->getNumber();

        if (!empty($seasonsNumber)) {
            $season = $seasonsNumber . ' ' . $ccdnConf->serial_season_field_suffix;
        }
        if (!empty($episodesNumber)) {
            $episode = $episodesNumber . ' ' . $ccdnConf->serial_episode_field_suffix;
        }


        $videoVoicesDisabled = (array)$ccdnConf->getJsonDecode('video_voices_disabled');

        $iframeUrl = $response->getIframeUrl()->addQueryParam('soundBlock', implode(',', $videoVoicesDisabled))->get();

        $firstVoice = $response->getVoicesActing()
            ->removeFromList($videoVoicesDisabled)
            ->getVoiceActingByPriority($ccdnConf->getJsonDecode('video_voice_priority'));

        global $member_id, $config;

        $categoryPost = new PostCategories();
        $categoryPostArr = $categoryPost->make($ccdnConf, $response);
        $post = new Post();


        $post->title = $response->getName();
        $post->metatitle = $response->getName();
        $post->alt_name = URLify::filter($response->getName(), 190);
        $post->date = date('Y-m-d H:i:s');
        $post->autor = $member_id['name'];
        $post->approve = $ccdnConf->new_franchise_approve;
        $post->category = $categoryPostArr->implode();
        $post->allow_comm = $config['allow_comments'];
        $post->allow_main = '1';

        if ($ccdnConf->new_franchise_description === '1') {
            $post->full_story = $response->getDescription();
        }

        if ($ccdnConf->new_franchise_short_desc === '1') {
            $post->short_story = $response->getDescription();
        }

        if ($config['create_metatags'] === '1' && $ccdnConf->new_franchise_description === '1') {
            $meta = create_metatags($response->getDescription());
            $post->descr = $meta['description'];
            $post->keywords = $meta['keywords'];
        }

        $premierFormatDate = !empty($ccdnConf->premier_format_date) ? $ccdnConf->premier_format_date : 'Y-m-d';

        $iframeUrl = $ccdnConf->content_ads_filter === '1' && $response->getAds() ? '' : $iframeUrl;
        $post->setField($ccdnConf->episode_count_field, $response->getSeasons()->getAllEpisodesCount());
        $post->setField($ccdnConf->post_status_field, '1');
        $post->setField($ccdnConf->new_franchise_origin_name, $response->getNameEng());
        $post->setField($ccdnConf->new_franchise_poster, $response->getPoster());
        $post->setField($ccdnConf->new_franchise_year, $response->getYear());
        $post->setField($ccdnConf->new_franchise_country, $response->getCountries()->implode());
        $post->setField($ccdnConf->new_franchise_director, $response->getDirectors()->implode());
        $post->setField($ccdnConf->new_franchise_actors, $response->getActors()->implode());
        $post->setField($ccdnConf->video_voice_field,
            $response->getVoicesActing()->removeFromList($videoVoicesDisabled)->implode());
        $post->setField($ccdnConf->video_first_voice_field, $firstVoice);
        $post->setField($ccdnConf->new_franchise_age, $response->getAge());
        $post->setField($ccdnConf->new_franchise_time, $response->getTime());
        $post->setField($ccdnConf->new_franchise_premier,
            langdate($premierFormatDate, strtotime($response->getPremier())));
        $post->setField($ccdnConf->new_franchise_premier_rus,
            langdate($premierFormatDate, strtotime($response->getPremierRus())));
        $post->setField($ccdnConf->new_franchise_genres, $response->getGenres()->implode());
        $post->setField($ccdnConf->video_quality_field, $response->getQuality());
        $post->setField($ccdnConf->imdb_id_field, $response->getImdbId());
        $post->setField($ccdnConf->world_art_id_field, $response->getWorldArtId());
        $post->setField($ccdnConf->kinopoisk_id_field, $response->getKinopoiskId());
        $post->setField($ccdnConf->new_franchise_rating_imdb, $response->getImdbRating());
        $post->setField($ccdnConf->new_franchise_rating_kinopoisk, $response->getKinopoiskRating());
        $post->setField($ccdnConf->new_franchise_rating_world_art, $response->getWorldArtRating());
        $post->setField($ccdnConf->new_franchise_trailer, $response->getTrailers()->getLast()->getIframeUrl()->get());
        $post->setField($ccdnConf->embed_field, $iframeUrl);
        $post->setField($ccdnConf->serial_season_field, $season);
        $post->setField($ccdnConf->serial_episode_field, $episode);
        $post->setField($ccdnConf->ccdn_id_field, $response->getId());
        $post->setField($ccdnConf->collaps_franchise_ads_status_field, (int)$response->getAds());
        $post->setField($ccdnConf->season_franchise_status, $response->getSerialStatus()->toCyrillic());

        $post->setField($ccdnConf->new_franchise_name, $response->getName());
        $post->setField($ccdnConf->new_franchise_slogan, $response->getSlogan());
        $post->setField($ccdnConf->new_franchise_screenwriter, $response->getScreenwriters()->implode());
        $post->setField($ccdnConf->new_franchise_producer, $response->getProducers()->implode());
        $post->setField($ccdnConf->new_franchise_operator, $response->getOperators()->implode());
        $post->setField($ccdnConf->new_franchise_composer, $response->getComposers()->implode());
        $post->setField($ccdnConf->new_franchise_design, $response->getDesigns()->implode());
        $post->setField($ccdnConf->new_franchise_editor, $response->getEditors()->implode());
        $post->setField($ccdnConf->new_franchise_actors_dubbing, $response->getActorsDuplicators()->implode());
        $post->setField($ccdnConf->new_franchise_budget, $response->getBudget());
        $post->setField($ccdnConf->new_franchise_fees_use, $response->getFeesUSA());
        $post->setField($ccdnConf->new_franchise_fees_rus, $response->getFeesRus());
        $post->setField($ccdnConf->new_franchise_fees_world, $response->getFeesWorld());
        $post->setField($ccdnConf->new_franchise_rate_mpaa, $response->getRateMPAA());
        $post->setField($ccdnConf->new_franchise_trivia, $response->getTrivia()->implode("\n\n"));
        $post->setField($ccdnConf->new_franchise_filed_description, $response->getDescription());
        $post->setField($ccdnConf->collection_field, $response->getCollection()->implode());
        $post->setField($ccdnConf->new_franchise_franchise_type, $response->getType()->getName());

        if ($response->getType()->isSeasons()) {
            $post->title = SeasonsFranchiseTitle::handler($ccdnConf, $response, $post);
            $post->alt_name = SeasonsFranchiseAltUrl::handler($ccdnConf, $response, $post);
            $post->metatitle = SeasonsFranchiseMetaTitle::handler($ccdnConf, $response, $post);
        } else {
            $post->title = NotSeasonsFranchiseTitle::handler($ccdnConf, $response, $post);
            $post->alt_name = NotSeasonsFranchiseAltUrl::handler($ccdnConf, $response, $post);
            $post->metatitle = NotSeasonsFranchiseMetaTitle::handler($ccdnConf, $response, $post);
        }

        if ($config['create_catalog'] === '1') {
            $post->symbol = $post->getDb()->safesql(dle_substr(htmlspecialchars(strip_tags(stripslashes(trim($post->title))),
                ENT_QUOTES, $config['charset']), 0, 1, $config['charset']));
        }

        $insertPostCondition = $post->insertPost($categoryPost->toArray());

        if (!empty($ccdnConf->new_franchise_download_poster) && $response->getPoster() !== null) {
            $result = CCDNUploadPoster::upload($ccdnConf, $response, $post->id);
            if (!empty($result['xfvalue'])) {
                $post->setField($ccdnConf->new_franchise_download_poster, $result['xfvalue']);
                $post->setField($ccdnConf->new_franchise_download_poster_url, '/uploads/posts/' . $result['xfvalue']);
                $post->setField($ccdnConf->new_franchise_download_poster_url_with_domain,
                    Url::getDomain() . '/uploads/posts/' . $result['xfvalue']);
                $post->updatePost();
            }
        }

        return Response::json([
            'status' => $insertPostCondition ? 'ok' : 'Insert error',
            'item' => [
                'collaps_id' => $response->getId(),
                'name' => $response->getName(),
            ],
            'upload' => $result
        ]);

    }
}
