<?php

namespace App\Services;

use App\Mail\MissingSongRequest;
use App\Models\ServiceSong;
use App\Models\Song;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Mail;

class SongMatchingService
{
    public function __construct(
        private readonly SongPrefixPostfixService $songPrefixPostfixService,
    ) {}

    public function autoMatch(ServiceSong $serviceSong): bool
    {
        if ($serviceSong->song_id !== null) {
            return false;
        }

        $song = null;

        if ($serviceSong->cts_ccli_id !== null && $serviceSong->cts_ccli_id !== '') {
            $song = Song::where('ccli_id', $serviceSong->cts_ccli_id)->first();
        }

        if ($song === null && $serviceSong->cts_song_id) {
            $song = Song::where('cts_song_id', $serviceSong->cts_song_id)->first();
        }

        if ($song === null) {
            return false;
        }

        // Find default arrangement: is_default → name='normal' → first
        $defaultArrangement = $song->arrangements()
            ->where('is_default', true)
            ->first() ?? $song->arrangements()
            ->where('name', 'normal')
            ->first() ?? $song->arrangements()
            ->first();

        $serviceSong->update([
            'song_id' => $song->id,
            'song_arrangement_id' => $defaultArrangement?->id,
            'matched_at' => Carbon::now(),
            'use_translation' => $song->has_translation,
        ]);

        return true;
    }

    /**
     * Manually assign a song to a service song.
     * Overwrites any existing assignment.
     * Only sets arrangement if currently null (preserves existing selection).
     */
    public function manualAssign(ServiceSong $serviceSong, Song $song): void
    {
        $updateData = [
            'song_id' => $song->id,
            'matched_at' => Carbon::now(),
            'use_translation' => $song->has_translation,
        ];

        // Bei Aenderung des Songs muss die Zuordnung neu bestaetigt werden.
        if ($serviceSong->song_id !== $song->id) {
            $updateData['confirmed_at'] = null;
        }

        // Only set arrangement if currently null
        if ($serviceSong->song_arrangement_id === null) {
            // Find default arrangement: is_default → name='normal' → first
            $defaultArrangement = $song->arrangements()
                ->where('is_default', true)
                ->first() ?? $song->arrangements()
                ->where('name', 'normal')
                ->first() ?? $song->arrangements()
                ->first();

            $updateData['song_arrangement_id'] = $defaultArrangement?->id;
        }

        $serviceSong->update($updateData);

        $this->songPrefixPostfixService->ensure($song);
    }

    /**
     * Send a missing song request email and record the timestamp.
     */
    public function requestCreation(ServiceSong $serviceSong): void
    {
        $service = $serviceSong->service;

        $recipientEmail = (string) Config::get('services.song_request.email', 'songs@example.com');

        Mail::to($recipientEmail)->send(new MissingSongRequest(
            songName: $serviceSong->cts_song_name,
            ccliId: $serviceSong->cts_ccli_id,
            service: $service,
        ));

        $serviceSong->update([
            'request_sent_at' => Carbon::now(),
        ]);
    }

    /**
     * Remove song assignment from a service song.
     */
    public function unassign(ServiceSong $serviceSong): void
    {
        $serviceSong->update([
            'song_id' => null,
            'matched_at' => null,
            'confirmed_at' => null,
        ]);
    }
}
