<?php

namespace Inside\IIDE\Console;

use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Inside\Content\Models\Contents\CommercialFirms;
use Inside\Content\Models\Contents\ProjectFolders;
use Inside\Content\Models\Contents\ProjectNews;
use Inside\Content\Models\Contents\Projects;
use Inside\Host\Bridge\BridgeContent;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Carbon;

class ImportProjectsDateLastChangedFromApi extends Command
{
    /**
     * @var string
     */
    protected $name = 'iide:projects:import-date';

    /**
     * @var string
     */
    protected $signature = 'iide:projects:import-date {--offset=0}';

    /**
     * @var string
     */
    protected $description = 'Import des dates de dernière mise à jour des projets depuis l\'API';

    private string $token = "";

    /**
     * @var int
     */
    private int $createdProjectsCount = 0;

    /**
     * @var Client
     */
    private $client;

    /**
     * @var mixed
     */
    private $projectDetails;

    private string $apiUrl;

    public function __construct()
    {
        parent::__construct();
        $this->client = new Client();
        $this->apiUrl = env('IIDE_PROJECT_API_URL', 'https://www.groupeidec-info.com/api');
    }

    /**
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function handle()
    {
        $this->setAuthToken();
        $this->createProjects();
        $this->getOutput()->writeln('<fg=green>End of import ('. $this->createdProjectsCount .')✔</fg=green>');
        Log::channel('import')->info('[Projects] End of import ('. $this->createdProjectsCount .') !');
    }

    /**
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function createProjects()
    {
        Log::channel('import')->info('[Projects] Import started !');
        $offset = intval($this->option('offset'));
        $projects = $this->getProjects($offset);

        while (!empty($projects->data)) {
            foreach ($projects->data as $project) {
                $mainContentUuid = $this->createProjectContent($project->id, 'fr');
                if (!$mainContentUuid) {
                    continue;
                }

                $this->createProjectContent($project->id, 'en', $mainContentUuid);
            }
            Log::channel('import')->info('[Projects] offset '. $offset .' !');
            $offset += 10;
            $projects = $this->getProjects($offset);
        }
    }

    /**
     * @param string $projectId
     * @param string $languageCode
     * @param string $mainContentUuid
     * @return string|null
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function createProjectContent(string $projectId, string $languageCode, string $mainContentUuid = ''): ?string
    {
        $this->projectDetails = $this->getProjectDetails($projectId, $languageCode);

        $projectContent = $this->buildProjectContent($languageCode);
        if ($projectContent === null) {
            $this->getOutput()->writeln('<fg=red>Import skipped / Empty title x</fg=red>');
            Log::channel('import')->info('[Projects] ['. $languageCode .'] [projectId:' . $projectId . '] Import skipped / Empty title x !');
            return null;
        }

        $bridge = new BridgeContent();

        $existingProject = Projects::query()
            ->where('project_id', $projectContent['project_id'])
            ->first();

        $uuid = null;

        if ($existingProject) {
            $projectContent['uuid'] = $existingProject->uuid;
            $uuid = $bridge->contentUpdate('projects', $projectContent);
            $this->getOutput()->writeln('<fg=green>'. $projectContent['title'] .' / updated ✔</fg=green>');
            Log::channel('import')->info('[Projects] ['. $languageCode .'] [projectId:' . $projectId . '] updated !');
        }

        return $uuid;
    }

    /**
     * @param int $offset
     * @param int $limit
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function getProjects(int $offset = 0, int $limit = 10)
    {
        $response = $this->client->request('GET', $this->apiUrl.'/projects', [
            'headers'   => [
                'Accept' => 'application/json',
                'Content-type' => 'application/json',
                'Authorization' => "Bearer {$this->token}",
            ],
            'query' => [
                'offset' => $offset,
                'limit' => $limit
            ]
        ]);

        if ($response->getStatusCode() !== 200) {
            throw new \Exception("An error occured while trying to fetch data from the api !");
        }

        return json_decode($response->getBody());
    }

    /**
     * @param string $projectId
     * @param string $languageCode
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function getProjectDetails(string $projectId, string $languageCode)
    {
        $response = $this->client->request('GET', $this->apiUrl.'/projects/' . $projectId, [
            'headers'   => [
                'Accept' => 'application/json',
                'Content-type' => 'application/json',
                'Authorization' => "Bearer {$this->token}",
            ],
            'query' => [
                'locale' => $languageCode,
            ]
        ]);

        if ($response->getStatusCode() !== 200) {
            throw new \Exception("An error occured while trying to get project details !");
        }

        return json_decode($response->getBody());
    }

    /**
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function setAuthToken()
    {
        $response = $this->client->request('POST', $this->apiUrl.'/login', [
            'form_params' => [
                'username' => 'idec-mobile',
                'password' => 'oij262#dd-PbDSR',
            ]
        ]);

        if ($response->getStatusCode() !== 200) {
            throw new \Exception("An error occured while trying to login to the api !");
        }

        $jsonResponse = json_decode($response->getBody());
        $this->token = $jsonResponse->token;
    }

    /**
     * @param string $languageCode
     * @return array|null
     * @throws \Exception
     */
    private function buildProjectContent(string $languageCode)
    {
        $contentTitle = $this->getProjectTitle();
        if (!$contentTitle) {
            return null;
        }

        $dateLastChanged = $this->getAttributeValueFromProject('dateLastChanged');

        if (! $dateLastChanged) {
            Log::channel('import')->info("[Projects] $contentTitle doesn't have valid dateLastChanged : $dateLastChanged");

            return null;
        }

        $date = Carbon::createFromFormat(
            format: 'd/m/Y',
            time: $dateLastChanged
        );

        if (! $date) {
            Log::channel('import')->info("[Projects] $contentTitle doesn't have valid dateLastChanged : $dateLastChanged");

            return null;
        }

        $content = [
            'type'                      => 'node',
            'bundle'                    => 'projects',
            'langcode'                  => $languageCode,
            'project_id'                => $this->getAttributeValueFromProject('id'),
            'title'                     => $contentTitle,
            'created_at'                => $date,
            'updated_at'                => $date,
            'published_at'              => $date,
        ];

        return $content;
    }

    /**
     * @param string $attributeName
     * @param string $subFieldName
     * @return string|null
     */
    private function getAttributeValueFromProject(string $attributeName, string $subFieldName = '')
    {
        if (!isset($this->projectDetails->{$attributeName}) || empty($this->projectDetails->{$attributeName})) {
            return null;
        }

        if ($subFieldName) {
            return $this->projectDetails->{$attributeName}->{$subFieldName};
        }

        return $this->projectDetails->{$attributeName};
    }

    /**
     * @return string|null
     */
    private function getProjectTitle()
    {
        return $this->getAttributeValueFromProject('title') ?: $this->getAttributeValueFromProject('internalTitle');
    }
}
