<?php

namespace App\Services;

use App\Models\Label;
use App\Models\Setting;
use App\Models\Song;
use App\Models\SongArrangement;
use App\Models\SongArrangementSection;
use App\Models\SongSection;
use Illuminate\Support\Facades\DB;

class SongPrefixPostfixService
{
    public function ensure(Song $song): void
    {
        DB::transaction(function () use ($song): void {
            $prefixLabelId = $this->resolvePrefixLabelId();
            $postfixLabelId = $this->resolvePostfixLabelId();

            $prefixSection = $this->ensureLockedSection($song, $prefixLabelId, 0, 'prefix');
            $postfixSection = $this->ensureLockedSection($song, $postfixLabelId, PHP_INT_MAX, 'postfix');

            $arrangement = $this->resolveDefaultArrangement($song);

            $this->ensureSectionInArrangement($arrangement, $prefixSection, 'first');
            $this->ensureSectionInArrangement($arrangement, $postfixSection, 'last');
        });
    }

    private function resolvePrefixLabelId(): int
    {
        $id = Setting::get('song_prefix_label_id');

        if ($id !== null && $id !== '') {
            return (int) $id;
        }

        $label = Label::firstOrCreate(
            ['name' => 'COPYRIGHT'],
            ['color' => '#24B34C'],
        );

        Setting::set('song_prefix_label_id', (string) $label->id);

        return $label->id;
    }

    private function resolvePostfixLabelId(): int
    {
        $id = Setting::get('song_postfix_label_id');

        if ($id !== null && $id !== '') {
            return (int) $id;
        }

        $label = Label::firstOrCreate(
            ['name' => 'BLANK'],
            ['color' => '#000000'],
        );

        Setting::set('song_postfix_label_id', (string) $label->id);

        return $label->id;
    }

    /**
     * @param  'prefix'|'postfix'  $kind
     */
    private function ensureLockedSection(Song $song, int $labelId, int $orderHint, string $kind): SongSection
    {
        $section = SongSection::firstOrCreate(
            ['song_id' => $song->id, 'label_id' => $labelId],
            ['order' => $orderHint, 'locked' => true],
        );

        $section->update(['locked' => true]);
        $section->slides()->delete();

        $textContent = $kind === 'prefix'
            ? $this->buildCopyrightText($song)
            : '';

        $section->slides()->create([
            'order' => 1,
            'text_content' => $textContent,
        ]);

        return $section;
    }

    private function buildCopyrightText(Song $song): string
    {
        $title = trim((string) ($song->title ?? $song->name ?? ''));

        $lines = [];

        if ($title !== '') {
            $lines[] = $title;
        }

        if (trim((string) $song->author) !== '') {
            $lines[] = trim((string) $song->author);
        }

        if (trim((string) $song->copyright_text) !== '') {
            $lines[] = trim((string) $song->copyright_text);
        }

        if (trim((string) $song->ccli_id) !== '') {
            $lines[] = 'CCLI-Liednr. '.trim((string) $song->ccli_id);
        }

        return implode("\n", $lines);
    }

    private function resolveDefaultArrangement(Song $song): SongArrangement
    {
        return SongArrangement::firstOrCreate(
            ['song_id' => $song->id, 'name' => 'normal'],
            ['is_default' => true],
        );
    }

    private function ensureSectionInArrangement(
        SongArrangement $arrangement,
        SongSection $section,
        string $position,
    ): void {
        $existing = SongArrangementSection::where('song_arrangement_id', $arrangement->id)
            ->where('song_section_id', $section->id)
            ->first();

        if ($position === 'first') {
            if ($existing === null) {
                SongArrangementSection::where('song_arrangement_id', $arrangement->id)
                    ->increment('order');

                SongArrangementSection::create([
                    'song_arrangement_id' => $arrangement->id,
                    'song_section_id' => $section->id,
                    'order' => 0,
                ]);
            } else {
                if ($existing->order !== 0) {
                    SongArrangementSection::where('song_arrangement_id', $arrangement->id)
                        ->where('id', '!=', $existing->id)
                        ->where('order', '<', $existing->order)
                        ->increment('order');

                    $existing->update(['order' => 0]);
                }
            }
        } else {
            $maxOrder = SongArrangementSection::where('song_arrangement_id', $arrangement->id)
                ->where('song_section_id', '!=', $section->id)
                ->max('order') ?? 0;

            if ($existing === null) {
                SongArrangementSection::create([
                    'song_arrangement_id' => $arrangement->id,
                    'song_section_id' => $section->id,
                    'order' => $maxOrder + 1,
                ]);
            } else {
                $existing->update(['order' => $maxOrder + 1]);
            }
        }
    }
}
