<?php

namespace App\Services;

use App\Models\Macro;
use App\Models\MacroAssignment;
use App\Models\MacroCollection;
use App\Models\Setting;
use App\Services\DTO\MacroImportResult;
use App\Support\MacroColorConverter;
use Illuminate\Support\Facades\DB;
use ProPresenter\Parser\MacrosFileReader;

class MacrosImportService
{
    public function import(string $filePath, string $originalFilename): MacroImportResult
    {
        $library = MacrosFileReader::read($filePath);
        $stats = ['new' => 0, 'updated' => 0, 'disabled' => 0, 'reEnabled' => 0];
        $importedUuids = [];

        DB::transaction(function () use ($library, &$stats, &$importedUuids, $originalFilename): void {
            foreach ($library->getMacros() as $parserMacro) {
                $uuid = strtoupper($parserMacro->getUuid());
                if ($uuid === '') {
                    continue;
                }
                $importedUuids[] = $uuid;
                $color = MacroColorConverter::fromRgba($parserMacro->getColor());
                $data = [
                    'uuid' => $uuid,
                    'name' => $parserMacro->getName(),
                    'color' => $color,
                    'trigger_on_startup' => $parserMacro->getTriggerOnStartup(),
                    'image_type' => $parserMacro->getImageType(),
                    'action_count' => $parserMacro->getActionCount(),
                    'last_imported_at' => now(),
                    'last_imported_filename' => $originalFilename,
                    'hidden_at' => null,
                ];

                $existing = Macro::where('uuid', $uuid)->first();
                if ($existing === null) {
                    Macro::create($data);
                    $stats['new']++;
                } else {
                    $wasHidden = $existing->isHidden();
                    $existing->update($data);
                    if ($wasHidden) {
                        $stats['reEnabled']++;
                    } else {
                        $stats['updated']++;
                    }
                }
            }

            if (! empty($importedUuids)) {
                $stats['disabled'] = Macro::whereNotIn('uuid', $importedUuids)
                    ->whereNull('hidden_at')
                    ->update(['hidden_at' => now()]);
            }

            foreach ($library->getCollections() as $parserCollection) {
                $collUuid = strtoupper($parserCollection->getUuid());
                if ($collUuid === '') {
                    continue;
                }

                $collection = MacroCollection::updateOrCreate(
                    ['uuid' => $collUuid],
                    ['name' => $parserCollection->getName(), 'last_imported_at' => now()],
                );

                $collection->macros()->detach();
                foreach ($parserCollection->getMacroUuids() as $idx => $macroUuid) {
                    $macro = Macro::where('uuid', strtoupper($macroUuid))->first();
                    if ($macro) {
                        $collection->macros()->attach($macro->id, ['order' => $idx]);
                    }
                }
            }
        });

        Setting::set('macros_last_imported_at', now()->toIso8601String());
        Setting::set('macros_last_imported_filename', $originalFilename);

        $warnings = $this->buildAssignmentWarnings();

        return new MacroImportResult(
            $stats['new'],
            $stats['updated'],
            $stats['disabled'],
            $stats['reEnabled'],
            $warnings,
        );
    }

    private function buildAssignmentWarnings(): array
    {
        return MacroAssignment::whereHas('macro', fn ($q) => $q->whereNotNull('hidden_at'))
            ->with('macro')
            ->get()
            ->map(fn ($a) => [
                'macro_name' => $a->macro->name,
                'macro_uuid' => $a->macro->uuid,
                'part_type' => $a->part_type,
            ])
            ->toArray();
    }
}
