<?php

namespace App\Http\Controllers;

use App\Clients\ItgApiClient;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

class SendDataController extends Controller
{
    public function __construct(
        private readonly ItgApiClient $itgApiClient
    ) {
    }

    public function acceptDataAction(Request $request): bool|string
    {
        $fair = $request->session()->get('fair');
        $accountData = $request->session()->get('account');
        $expositionData = $request->session()->get('exposition');
        $worksData = $request->session()->get('works');

        $data = $request->validate([
            'user_id' => '',
            'gallery_id' => '',
        ]);

        $account = $this->getOrCreateAccount($data, $accountData);
        $magicLink = $this->itgApiClient->createMagicLink($account->user_id);
        $this->itgApiClient->setAccessToken(
            $request->session()->has('itg_access_token')
                ? $request->session()->get('itg_access_token')
                : $this->itgApiClient->authenticateAsUser($account->user_id)
        );
        $exposition = $this->getOrCreateExposition($expositionData, $account, $fair);
        $artistMap = [];
        $errorOnSomeWorks = false;
        if (!empty($worksData)) {
            foreach ($worksData as $workData) {
                try {
                    if (empty($workData['selected_edition'])) {
                        if (!isset($artistMap[$workData['artist_name']])) {
                            $artist = $this->getOrCreateArtist($workData['artist_name'], $account);
                            $artistMap[$workData['artist_name']] = $artist->id;
                        }
                        $work = $this->itgApiClient->createWork([
                            'title' => $workData['name'],
                            'artist_id' => $artistMap[$workData['artist_name']],
                            'description' => $workData['description'],
                            'main_image' => $workData['main_image'],
                            'technique' => $workData['technique'],
                            'dimensions' => $workData['dimensions'],
                            'prices' => $workData['selected_price'] ? [$workData['selected_price']] : [],
                            'gallery_id' => $account->gallery_id,
                            'year' => $workData['year'],
                            'availability' => 'available',
                            'status_id' => 1
                        ]);
                        $this->itgApiClient->addWorkToExposition($work->id, $exposition->id);
                    } else {
                        $this->itgApiClient->addWorkToExposition($workData['selected_edition']['work_id'], $exposition->id);
                    }
                } catch (\Exception) {
                    $errorOnSomeWorks = true;
                    Log::error("Error al crear la obra {$workData['name']}");
                }
            }
        }
        $galleryExhibifyIntegration = $this->getOrCreateGalleryExhibifyIntegration($account);
        $expositionExhibifyIntegration = $this->itgApiClient->getExpositionExhibifyIntegration($exposition->id);
        if (empty($expositionExhibifyIntegration)) {
            $this->itgApiClient->createExpositionExhibifyIntegration(
                $exposition->id,
                $galleryExhibifyIntegration->id,
                $fair->collection_id,
                $this->generateWorkIntegrationData($worksData)
            );
        }
        $redirectUrl = $magicLink . '&r=' . urlencode($exposition->view_url);
        $this->saveExpositionUrl($fair, $exposition);
        return json_encode([
            'redirect_url' => $redirectUrl,
            'message' => "En breve se le redireccionará a Exhibify." . ($errorOnSomeWorks
                ? "\nNo se han podido crear todas las obras. Por favor, revise los datos en Exhibify"
                : "")
        ]);
    }

    /**
     * @param array $data
     * @param mixed $accountData
     * @return mixed|object
     */
    public function getOrCreateAccount(array $data, mixed $accountData): mixed
    {
        if (empty($data['user_id']) || empty($data['gallery_id'])) {
            $account = $this->itgApiClient->register(
                [
                    'email' => $accountData['email'],
                    'gallery_name' => $accountData['gallery_name'],
                    'gallery_main_image' => !empty($accountData['gallery_main_image'])
                        ? base_path($accountData['gallery_main_image'])
                        : '',
                    'gallery_description' => $accountData['gallery_description'],
                    'gallery_city' => $accountData['gallery_city'],
                    'gallery_country' => $accountData['gallery_country'],
                    'gallery_address' => $accountData['gallery_address'],
                    'language' => $accountData['language'],
                    'licence_type' => 'EXHIBIFY_FREE_FAIRS',
                    'rol_id' => 6
                ]
            );
        } else {
            $account = (object)[
                'user_id' => $data['user_id'],
                'gallery_id' => $data['gallery_id']
            ];
        }
        return $account;
    }

    /**
     * @param mixed $expositionData
     * @param mixed $account
     * @param mixed $fair
     * @return mixed
     */
    public function getOrCreateExposition(mixed $expositionData, mixed $account, mixed $fair): mixed
    {
        if (empty($expositionData['id'])) {
            $exposition = $this->itgApiClient->createExposition([
                'name' => $expositionData['name'],
                'description' => $expositionData['description'],
                'main_image' => filter_var($expositionData['main_image'], FILTER_VALIDATE_URL)
                    ? $expositionData['main_image']
                    : base_path($expositionData['main_image']),
                'opening_date' => $expositionData['opening_date'],
                'closing_date' => $expositionData['closing_date'],
                'type_id' => 1,
                'gallery_id' => $account->gallery_id,
                'exhibify_fair_id' => $fair->id,
            ]);
        } else {
            $exposition = $this->itgApiClient->getExposition($expositionData['id']);
            $this->itgApiClient->assignExpositionToExhibifyFair($exposition->id, $fair->id);
        }
        return $exposition;
    }

    /**
     * @param $artistName1
     * @param mixed $account
     * @return mixed
     */
    public function getOrCreateArtist($artistName1, mixed $account): mixed
    {
        $existingArtists = $this->itgApiClient->getArtistsByName(
            $artistName1,
            $account->gallery_id
        );
        if (!empty($existingArtists->data)) {
            $artist = $existingArtists->data[0];
        } else {
            [$artistName, $artistSurname] = explode(' ', $artistName1, 2);
            $artist = $this->itgApiClient->createArtist([
                'name' => $artistName,
                'surname' => $artistSurname,
                'complete_name' => $artistName1,
                'gallery_id' => $account->gallery_id,
            ]);
        }
        return $artist;
    }

    /**
     * @param mixed $account
     * @return array|mixed
     */
    public function getOrCreateGalleryExhibifyIntegration(mixed $account): mixed
    {
        $galleryExhibifyIntegration = $this->itgApiClient->getGalleryExhibifyIntegration($account->gallery_id);
        if (empty($galleryExhibifyIntegration)) {
            $galleryExhibifyIntegration = $this->itgApiClient->createGalleryExhibifyIntegration($account->gallery_id);
        }
        return $galleryExhibifyIntegration;
    }

    private function generateWorkIntegrationData(array $worksData): array
    {
        $workIntegrationData = [];
        foreach ($worksData as $work) {
            if (!empty($work['selected_edition'])) {
                $workIntegrationData[$work['selected_edition']['work_id']] = [
                    'work_edition_id' => $work['selected_edition']['id'],
                    'price_currency_iso_code' => $work['selected_price']['currency'] ?? null,
                    'price_type_id' => $work['selected_price']['type_id'] ?? null,
                    'dimension_unit' => $work['dimensions']['unit'] ?? null,
                    'dimension_type_id' => null,
                    'variable_measures' => 0,
                ];
            }
        }
        return $workIntegrationData;
    }
}
