<?php


namespace App\Services;
set_time_limit(0);
date_default_timezone_set('UTC');

use InstagramAPI\Response\Model\Item;
use InstagramAPI\Instagram;
use App\Instagram as Ins;
use InstagramScraper\Exception\InstagramException;

class InstagramService
{
    private $username = "nicksxs";
    private $password = 'tmx211314';
    private $debug = false;
    private $truncatedDebug = false;


    function traceExistFiles($dir)
    {
        $existFiles = [];
        if (is_dir($dir)) {
            $files = array_diff(scandir($dir), ['.', '..']);
            foreach ($files as $file) {
                if (isMedia($file)) {
                    $existFiles[] = $file;
                }
            }
            return $existFiles;
        }
        return [];
    }

    function isMedia($file)
    {
        if (in_array(pathinfo($file)['extension'], ['jpg', 'mp4'])) {
            return true;
        }
        return false;
    }

    function logFailUrl($filePrefix, $fileUrl)
    {
        $failLogFile = "fail.log";
        $myfile = file_put_contents($failLogFile, $filePrefix . "\t" . $fileUrl . PHP_EOL, FILE_APPEND | LOCK_EX);
    }

    function downloadFile($filenameUrl, $flag = 0, $filePrefix = "")
    {
        //echo $filenameUrl;exit;
        $filePathInfo = pathinfo($filenameUrl);
        $filename = $filePathInfo['filename'];
        //    echo $filename;
        //    echo "\n";
        $pos = strpos($filename, "?");
        //    echo "pos: ".$pos;
        //    echo "\n";
        if ($pos > 0) {
            $filename = substr($filename, 0, $pos);
        }
        //    if ($filename == "33020038_640464766303508_27725890796388352_n.jpg"){
        //        $flag = 1;
        //    }
        if (file_exists($filePrefix . $filename) || file_exists($filePrefix . $filename . ".back")) {
            echo "\n file exists " . $filePrefix . $filename;
            return 0;
        }
        try {
            $cn_match = "https://scontent-lax3-1.cdninstagram.com";
            $options = array(
                'ssl' => array(
                    'verify_peer' => true,
                    'cafile' => "/Users/shixuesen/Downloads/cacert.pem",
                    'ciphers' => 'HIGH:TLSv1.2:TLSv1.1:TLSv1.0:!SSLv3:!SSLv2',
                    'CN_match' => $cn_match,
                    'disable_compression' => true,
                )
            );
            $context = stream_context_create($options);
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $filenameUrl);
            curl_setopt($ch, CURLOPT_VERBOSE, 1);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_AUTOREFERER, false);
            curl_setopt($ch, CURLOPT_REFERER, "https://scontent-lax3-1.cdninstagram.com");
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $image = curl_exec($ch);
            curl_close($ch);
            //            $image = file_get_contents($filenameUrl, false, null);
        } catch (\Throwable $e) {
            var_dump($e);
            $this->logFailUrl($filePrefix, $filenameUrl);
            return -1;
        }

        echo "new filename: " . $filePrefix . $filename . "\n";
        $downloadResult = file_put_contents($filePrefix . $filename, $image);
        if (!$downloadResult) {
            $this->logFailUrl($filePrefix, $filenameUrl);
            return -1;
        } else {
            return 1;
        }
    }

    public function parseExactFileName($fileUrl)
    {
        $filePathInfo = pathinfo($fileUrl);
        $filename = $filePathInfo['filename'];
        $pos = strpos($filename, "?");
        if ($pos > 0) {
            $filename = substr($filename, 0, $pos);
        }
        return $filename;
    }

    public function checkFileExists($fileName, $isDb = true, $filePrefix = '')
    {
        if ($isDb) {
            return Ins::where('image_name', $fileName)->where('is_uploaded', 1)->count() > 0;
        } else {
            return file_exists($filePrefix . $fileName) || file_exists($filePrefix . $fileName . ".back");
        }
    }

    public function scrapeLikedUsers()
    {
        $ig = new Instagram($this->debug, $this->truncatedDebug);

        try {
            $ig->login($this->username, $this->password);
        } catch
        (\Exception $e) {
            echo 'Something went wrong: ' . $e->getMessage() . "\n";
            exit(0);
        }

        $baseImageDir = "/Users/shixuesen/OneDrive/Pictures/instagram/Likes/";
        try {
            $maxId = null;
            do {
                $response = $ig->media->getLikedFeed();
                foreach ($response->getItems() as $item) {
                    //echo json_encode($response->getItems());exit;
                    switch ($item->getMediaType()) {
                        case Item::PHOTO:
                            $imageUrl = $item->getImageVersions2()->getCandidates()[0]->getUrl();
                            $res = $this->downloadFile($imageUrl, 0, $baseImageDir);
                            break;
                        case Item::VIDEO:
                            $videoUrl = $item->getVideoVersions()[0]->getUrl();
                            $res = $this->downloadFile($videoUrl, 0, $baseImageDir);
                            break;
                        case Item::CAROUSEL:
                            //                            echo json_encode($item);
                            //                            exit;
                            foreach ($item->getCarouselMedia() as $imageItem) {
                                $imageUrl = $imageItem->getImageVersions2()->getCandidates()[0]->getUrl();
                                $res = $this->downloadFile($imageUrl, 0, $baseImageDir);
                            }
                            break;
                    }

                }

                // Now we must update the maxId variable to the "next page".
                // This will be a null value again when we've reached the last page!
                // And we will stop looping through pages as soon as maxId becomes null.
                $maxId = $response->getNextMaxId();
                echo "\n new maxId: " . $maxId . "\n";

                // Sleep for 5 seconds before requesting the next page. This is just an
                // example of an okay sleep time. It is very important that your scripts
                // always pause between requests that may run very rapidly, otherwise
                // Instagram will throttle you temporarily for abusing their API!
                echo "\n Sleeping for 5s...\n";
                sleep(5);
            } while ($maxId != null);
        } catch (\Exception $e) {
            echo 'Something went wrong: ' . $e->getMessage() . "\n";
        }
    }

    public function scrapeUsers()
    {
        $ig = new Instagram($this->debug, $this->truncatedDebug);

        try {
            $ig->login($this->username, $this->password);
        } catch
        (\Exception $e) {
            echo 'Something went wrong: ' . $e->getMessage() . "\n";
            exit(0);
        }

        $baseImageDir = "/Users/shixuesen/OneDrive/Pictures/instagram/";

        try {

            $userList = file("/Users/shixuesen/OneDrive/Pictures/instagram/user.txt");
            //            $userList = array_slice($userList, 17);
            //            $userList = ['1992.ai_'];
            //            print_r($userList);exit;
            //    print_r($userList);
            foreach ($userList as $userName) {
                $trueName = trim($userName);
                //                echo $trueName;exit;
                $thisUserImageDir = $baseImageDir . $trueName . "/";
                //                $existFiles = $this->traceExistFiles($thisUserImageDir);
                $userId = $ig->people->getUserIdForName(trim($userName));
                echo "username: " . $trueName . " " . $userId . "\n";
                //                continue;

                //                if ($trueName == 'sabrina888888_') {
                //                    echo "\n______________________\n";
                //                    $maxId = '1451179182821586881_19900699';
                //                } else {
                $response = $ig->story->getUserReelMediaFeed($userId);
                foreach ($response->getItems() as $item) {
                    if (Item::VIDEO == $item->getMediaType()) {
                        $videoUrl = $item->getVideoVersions()[0]->getUrl();
                        $res = $this->downloadFile($videoUrl, 0, $thisUserImageDir);
                    }
                }
//                echo $item[0]->getVideoVersions()[0]->getUrl();
                sleep(5);
                continue;
                $maxId = null;
                //                }
                do {
                    // Request the page corresponding to maxId.
                    echo "\n current maxId: " . $maxId;
                    $response = $ig->timeline->getUserFeed($userId, $maxId);
                    $response = $ig->story->getUserReelMediaFeed($userId);
                    dump($response);exit;
//                    $response->getPostLiveItem()->getBroadcasts()

                    // In this example we're simply printing the IDs of this page's items.
                    foreach ($response->getItems() as $item) {
                        switch ($item->getMediaType()) {
                            case Item::PHOTO:
                                $imageUrl = $item->getImageVersions2()->getCandidates()[0]->getUrl();
                                $res = $this->downloadFile($imageUrl, 0, $thisUserImageDir);
                                $filename = $this->parseExactFileName($imageUrl);
                                //                                Ins::firstOrCreate(['image_name' => $filename], [
                                //                                    'username' => $userName,
                                //                                    'image_url' => $imageUrl
                                //                                ]);
                                if ($res == 0) {
                                    goto a;
                                }
                                break;
                            case Item::VIDEO:
                                $videoUrl = $item->getVideoVersions()[0]->getUrl();
                                $res = $this->downloadFile($videoUrl, 0, $thisUserImageDir);
                                $filename = $this->parseExactFileName($videoUrl);
                                //                                Ins::firstOrCreate(['image_name' => $filename], [
                                //                                    'username' => $userName,
                                //                                    'image_url' => $videoUrl
                                //                                ]);
                                if ($res == 0) {
                                    goto a;
                                }
                                break;
                            case Item::CAROUSEL:
                                foreach ($item->getCarouselMedia() as $imageItem) {
                                    $imageUrl = $imageItem->getImageVersions2()->getCandidates()[0]->getUrl();
                                    $res = $this->downloadFile($imageUrl, 0, $thisUserImageDir);
                                    $filename = $this->parseExactFileName($imageUrl);
                                    //                                    Ins::firstOrCreate(['image_name' => $filename], [
                                    //                                        'username' => $userName,
                                    //                                        'image_url' => $imageUrl
                                    //                                    ]);
                                    if ($res == 0) {
                                        goto a;
                                    }
                                }
                                break;
                        }

                        //                printf("[%s] https://instagram.com/p/%s/\n", $item->getId(), $item->getCode());
                    }

                    // Now we must update the maxId variable to the "next page".
                    // This will be a null value again when we've reached the last page!
                    // And we will stop looping through pages as soon as maxId becomes null.
                    $maxId = $response->getNextMaxId();
                    echo "\n new maxId: " . $maxId . "\n";

                    // Sleep for 5 seconds before requesting the next page. This is just an
                    // example of an okay sleep time. It is very important that your scripts
                    // always pause between requests that may run very rapidly, otherwise
                    // Instagram will throttle you temporarily for abusing their API!
                    echo "\n Sleeping for 5s...\n";
                    sleep(10);
                } while ($maxId !== null); // Must use "!==" for comparison instead of "!=".
                a:
            }
            // Get the UserPK ID for "natgeo" (National Geographic).
            /**
             * $userId = $ig->people->getUserIdForName('nyanchan22');
             *
             * // Starting at "null" means starting at the first page.
             * $maxId = null;
             * do {
             * // Request the page corresponding to maxId.
             * $response = $ig->timeline->getUserFeed($userId, $maxId);
             *
             * // In this example we're simply printing the IDs of this page's items.
             * foreach ($response->getItems() as $item) {
             * printf("[%s] https://instagram.com/p/%s/\n", $item->getId(), $item->getCode());
             * }
             *
             * // Now we must update the maxId variable to the "next page".
             * // This will be a null value again when we've reached the last page!
             * // And we will stop looping through pages as soon as maxId becomes null.
             * $maxId = $response->getNextMaxId();
             *
             * // Sleep for 5 seconds before requesting the next page. This is just an
             * // example of an okay sleep time. It is very important that your scripts
             * // always pause between requests that may run very rapidly, otherwise
             * // Instagram will throttle you temporarily for abusing their API!
             * echo "Sleeping for 5s...\n";
             * sleep(5);
             * } while ($maxId !== null); // Must use "!==" for comparison instead of "!=".
             */
        } catch (\Exception $e) {
            echo 'Something went wrong: ' . $e->getMessage() . "\n";
        }
    }

    public function scanLocalFiles($baseDir = '/Users/shixuesen/OneDrive/Pictures/instagram/')
    {
        $dirs = scandir($baseDir, 1);
        foreach ($dirs as $subDir) {
            if ($subDir == '.' || $subDir == '..') {
                continue;
            }
            $subPath = $baseDir . $subDir;
            if (is_dir($subPath)) {
                $files = scandir($subPath);
                foreach ($files as $file) {
                    if ($file == '.' || $file == '..') {
                        continue;
                    }
                    echo "now file: " . $file . "\n";
                    Ins::firstOrCreate(['image_name' => $file], [
                        'username' => $subDir,
                        'is_uploaded' => 1,
                        'image_url' => ''
                    ]);
                }

            }
        }
    }

    public function testNewApi()
    {

    }
}
