<?php

namespace Database\Seeders;

use App\Models\GenericBackoffice\WebsiteObject;
use App\Models\GenericBackoffice\WebsiteObjectLanguage;
use App\Models\MapItem;
use App\Models\MapItemLanguage;
use App\Models\MapInformation;
use App\Models\MapInformationLanguage;
use Exception;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Throwable;

class MapItemsTableSeeder extends Seeder
{
    protected $languages;

    // Combination options
    protected $counterpartyTypes = [
        'corporate_corporate' => 'Corporate Corporate',
        'bank_corporate' => 'Bank Corporate',
        'bank_bank' => 'Bank Bank',
    ];

    protected $settlementTypes = [
        'physical' => 'Physical',
        'financial' => 'Financial',
    ];

    protected $relevantCommodities = [
        'power_gas' => 'Power Gas',
        'co2_allowances' => 'CO2 Allowances',
        'green_certificates' => 'Green Certificates',
        'mixed_portfolio' => 'Mixed Portfolio',
    ];

    public function __construct() {
        $this->languages = getAvailableLanguagesKeys();
    }

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::beginTransaction();
        try {
            $mapItems = $this->readMapItemsFromFile();
            $this->createMapItems($mapItems);
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            Log::error($e);
        }
    }

    protected function readMapItemsFromFile()
    {
        $filePath = storage_path('app/data/map_items.json');

        if (!file_exists($filePath)) {
            throw new Exception("The file map_items.json does not exist at $filePath");
        }

        $jsonContent = file_get_contents($filePath);

        $mapItems = json_decode($jsonContent, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("Error decoding JSON: " . json_last_error_msg());
        }

        return $mapItems;
    }

    protected function createMapItems($mapItems) {
        foreach ($mapItems as $item) {
            $existingMapItem = MapItem::find($item['id']);

            if ($existingMapItem) {
                Log::info("MapItem with ID {$item['id']} already exists. Skipping...");
                continue;
            }

            if (empty($item['id']) || empty($item['title'])) {
                Log::warning("MapItem with ID {$item['id']} is missing required fields. Skipping...");
                continue;
            }

            $mapItem = new MapItem();
            $mapItem->id = $item['id'];
            $mapItem->save();

            $mapItemLang = new MapItemLanguage();
            $mapItemLang->map_item_id = $item['id'];
            $mapItemLang->language_id = 'en';
            $mapItemLang->title = $item['title'];
            $mapItemLang->save();

            $slugs['en'] = urlize($item['title']);
            $this->createWebsiteObject($item['id'], MapItem::class, 'mapItem', $slugs, true);

            // Create all MapInformations for this MapItem

            $this->createMapInformations($item['id'], $item['title']);
        }
    }

    protected function createMapInformations($mapItemId, $countryTitle) {
        Log::info("Creating MapInformations for MapItem ID: {$mapItemId}");

        // Generate all combinations
        foreach ($this->counterpartyTypes as $counterpartyKey => $counterpartyLabel) {
            foreach ($this->settlementTypes as $settlementKey => $settlementLabel) {
                foreach ($this->relevantCommodities as $commodityKey => $commodityLabel) {
                    // Clean labels by removing hyphens and slashes, replacing with spaces
                    $cleanCounterparty = $this->cleanLabel($counterpartyLabel);
                    $cleanSettlement = $this->cleanLabel($settlementLabel);
                    $cleanCommodity = $this->cleanLabel($commodityLabel);

                    // Create the title by concatenating cleaned labels
                    $title = $cleanCounterparty . ' ' . $cleanSettlement . ' ' . $cleanCommodity;

                    // Create MapInformation
                    $mapInformation = new MapInformation();
                    $mapInformation->map_item_id = $mapItemId;
                    $mapInformation->counterparty_type = $counterpartyKey;
                    $mapInformation->settlement_type = $settlementKey;
                    $mapInformation->relevant_commodity = $commodityKey;
                    $mapInformation->color = 'none';
                    $mapInformation->backend_user_id = 1;
                    $mapInformation->save();

                    // Create MapInformationLanguage
                    $mapInformationLang = new MapInformationLanguage();
                    $mapInformationLang->map_information_id = $mapInformation->id;
                    $mapInformationLang->language_id = 'en';
                    $mapInformationLang->title = $title;
                    $mapInformationLang->counterparty_comment = null;
                    $mapInformationLang->comment = null;
                    $mapInformationLang->save();

                    // Create slug combining country name and combination
                    $slugTitle = $countryTitle . ' ' . $title;
                    $slugs['en'] = urlize($slugTitle);

                    // Create WebsiteObject for this MapInformation
                    $this->createWebsiteObject(
                        $mapInformation->id,
                        MapInformation::class,
                        'mapInformation',
                        $slugs,
                        true
                    );

                    Log::info("Created MapInformation: {$title} for {$countryTitle}");
                }
            }
        }
    }

    protected function cleanLabel($label) {
        // Remove hyphens and slashes, replace with spaces
        return str_replace(['-', '/'], ' ', $label);
    }

    protected function createWebsiteObject($id, $objectType, $contentType, $slugs, $isDraft = false, $position = null) {
        Log::info("Create Website Object");

        $obj = new WebsiteObject();
        $contentConfig = config('backoffice.generic.' . $contentType);

        $baseUri = '';
        if (!empty($contentConfig['baseUri']['en'])) {
            $baseUri = $contentConfig['baseUri']['en'];
        }

        $i = 0;
        $suffix = '';
        $defaultSlug = mb_substr(!empty($slugs['en']) ? $slugs['en'] : $slugs, 0, 100);
        while(
            WebsiteObject::where('slug', $defaultSlug . $suffix)->first()
        ) {
            $i++;
            $suffix = "-$i";
        }
        $slug = $defaultSlug . $suffix;

        $obj->object_id = $id;
        $obj->object_type = $objectType;
        $obj->slug = mb_substr($slug, 0, 150);
        $obj->status = $isDraft ? 'draft' : 'published';
        $obj->content_type = $contentType;
        $obj->uri = $baseUri . '/' . $obj->slug;
        $obj->position = $position;
        $obj->save();

        foreach ($this->languages as $lang) {
            $baseUri = '';
            if (!empty($contentConfig['baseUri'][$lang])) {
                $baseUri = $contentConfig['baseUri'][$lang] . '/';
            }

            $langObject = new WebsiteObjectLanguage();
            $langObject->website_object_id = $obj->website_object_id;
            $langObject->wo_language_id = $lang;

            $i = 0;
            $suffix = '';
            $slug = mb_substr(!empty($slugs[$lang]) ? $slugs[$lang] : $slugs, 0, 100);

            while(
                WebsiteObjectLanguage::where('lang_slug', $slug . $suffix)
                    ->where('wo_language_id', $lang)
                    ->first()
            ) {
                $i++;
                $suffix = "-$i";
            }
            $slug = $slug . $suffix;
            $langObject->lang_slug = mb_substr($slug, 0, 150);
            $langObject->lang_uri = $baseUri . $slug;
            $langObject->save();
        }
    }
}
