<?php

namespace App\Parser;

use App\ParsedHome;
use App\Parser;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

/**
 * Thanks to https://github.com/axeleroy/untoitpourcaramel/issues/3
 * Class SeLoger
 * @package App\Parser
 */
class SeLoger extends Parser
{
    public const TOKEN_URL = 'https://api-seloger.svc.groupe-seloger.com/api/v1/security/authenticate';
    public const LISTING_URL = 'https://api-seloger.svc.groupe-seloger.com/api/v1/listings/';
    public const SELOGER_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTZUxvZ2VyLW1vYmlsZSIsImFwcCI6IjYzZWU3MTRkLWE2MmEtNGEyNy05ZmJlLTQwYjdhMmMzMThlNCIsImlhdCI6MTUzOTQ0MjMyMCwianRpIjoiNWYzODRhNDYtZjk5MS00ODZkLWFkN2YtMmE2M2YxZTdkM2UwIiwiYXVkIjoiU2VMb2dlci1Nb2JpbGUtNi4wIn0.Qib13Y4395f_bi5Df0IhMQRvIxQZEfpf8Ac66oTfyiA';
    public const SELOGER_GUID = '63ee714d-a62a-4a27-9fbe-40b7a2c318e4';

    /**
     * @inheritDoc
     */
    public function parse(): ParsedHome
    {
        $token = $this->retrieveToken();
        $idAnnonce = $this->getIdAnnonceFromUrl($this->url);
        $url = sprintf('%s%s', self::LISTING_URL, $idAnnonce);
        try {
            $request = $this->client->request(
                'GET',
                $url,
                [
                    'headers' => [
                        'AppToken' => $token,
                    ],
                ]
            );
        } catch (GuzzleException $e) {
            return $this->parseHTML();
        }
        $annonce = json_decode($request->getBody()->getContents(), true);

        $parsedHome = new ParsedHome();
        $parsedHome->city = $annonce['city'];
        //ex: Vente maison 110 m² Tréguier (22220)
        $parsedHome->title = $annonce['title'];
        $parsedHome->price = $annonce['price'];
        $parsedHome->surface = $annonce['livingArea'];
        $parsedHome->rooms = $annonce['rooms'];
        $parsedHome->energy = $annonce['energy']['grade'];
        $parsedHome->description = $annonce['description'];
        $parsedHome->pictures = $annonce['photos'];
        $location = $annonce['coordinates'];
        $parsedHome->map = ['lat' => $location['latitude'], 'lng' => $location['longitude']];

        return $parsedHome;
    }

    /**
     * @param string $url
     *
     * @return string
     */
    private function getIdAnnonceFromUrl($url)
    {
        // ex : https://www.seloger.com/annonces/achat/maison/franconville-95/vieux-marche-mare-des-noues/159100953.htm
        $url = parse_url($url, PHP_URL_PATH);
        return collect(explode('.', collect(explode('/', $url))->last()))->first();
    }

    /**
     * @return string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function retrieveToken()
    {
        $request = $this->client->request(
            'GET',
            self::TOKEN_URL,
            [
                'headers' => [
                    'AppToken' => self::SELOGER_TOKEN,
                    'AppGuid'  => self::SELOGER_GUID,
                ],
            ]
        );

        return trim($request->getBody()->getContents(), '"');
    }

    /**
     * @return \App\ParsedHome
     */
    private function parseHTML()
    {
        $request = $this->client->get(
            $this->url,
            [
                'headers' => [
                    'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0',
                    'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'Accept-Encoding' => 'gzip, deflate, br',
                    'Accept-Language' => 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
                    'Cache-Control' => 'no-cache',
                    'Connection' => 'keep-alive',
                ]
            ]
        );
        $body = $request->getBody()->getContents();
        $crawler = new Crawler($body);

        $parsed_home = new ParsedHome();

        $parsed_home->title = $crawler->filter('h1')->text();
        $parsed_home->description = $crawler->filter('#showcase-description > div')->first()->text();
        $parsed_home->price = (int) str_replace(' ', '', $crawler->filter('[class^=Summarystyled__PriceText]')->text());
        $parsed_home->city = $crawler->filter('[class^=Summarystyled__Address]')->text();
        $parsed_home->energy = $this->calculateDPE(
            (int)$crawler->filter('[class^=Preview__PreviewTooltipValue]')->first()->text()
        );
        $parsed_home->ges = $this->calculateGES(
            (int)$crawler->filter('[class^=Preview__PreviewTooltipValue]')->eq(1)->text()
        );

        $crawler
            ->filter('[class^=Summarystyled__TagsWrapper] > div')
            ->each(static function (Crawler $property____information, $i) use (&$parsed_home) {
                $element = $property____information->children()->eq(1)->text();
                if ('pièces' === mb_substr($element, -6)) {
                    $parsed_home->rooms = (int) $element;
                }
                if ('m²' === mb_substr($element, -2) && strpos($element, '/') === false) {
                    $parsed_home->surface = (int) $element;
                }
            });

        $parsed_home->pictures = $crawler
            ->filter('.swiper-wrapper')
            ->first()
            ->filter('[data-background]')
            ->each(static function ($img) {
                return $img->attr('data-background');
            });

        return $parsed_home;
    }
}