<?php

namespace App\Models;

use App\Services\AgendaMatcherService;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Service extends Model
{
    use HasFactory;

    protected $fillable = [
        'cts_event_id',
        'title',
        'date',
        'preacher_name',
        'beamer_tech_name',
        'finalized_at',
        'last_synced_at',
        'cts_data',
        'has_agenda',
    ];

    protected function casts(): array
    {
        return [
            'date' => 'date',
            'finalized_at' => 'datetime',
            'last_synced_at' => 'datetime',
            'cts_data' => 'array',
            'has_agenda' => 'boolean',
        ];
    }

    public function serviceSongs(): HasMany
    {
        return $this->hasMany(ServiceSong::class);
    }

    public function slides(): HasMany
    {
        return $this->hasMany(Slide::class);
    }

    public function agendaItems(): HasMany
    {
        return $this->hasMany(ServiceAgendaItem::class)->orderBy('sort_order');
    }

    /**
     * Check finalization prerequisites and return warnings.
     *
     * @return array{ready: bool, warnings: string[]}
     */
    public function finalizationStatus(): array
    {
        $warnings = [];

        // Backward compatibility: if no agenda items exist, use old checks
        if ($this->agendaItems()->count() === 0) {
            return $this->finalizationStatusLegacy();
        }

        // New agenda-based checks
        $agendaItems = $this->agendaItems()->with('serviceSong.song')->get();

        // Check 1: Unmatched songs (song-type agenda items where song_id IS NULL)
        $unmatchedSongs = $agendaItems->filter(function (ServiceAgendaItem $item) {
            if ($item->service_song_id === null) {
                return false;
            }
            $serviceSong = $item->serviceSong;

            return $serviceSong && $serviceSong->song_id === null;
        });

        foreach ($unmatchedSongs as $item) {
            $songName = $item->serviceSong?->cts_song_name ?? 'Unbekannter Song';
            $warnings[] = "{$songName} wurde noch nicht zugeordnet";
        }

        // Check 2: Matched songs without arrangement
        $matchedSongsWithoutArrangement = $agendaItems->filter(function (ServiceAgendaItem $item) {
            if ($item->service_song_id === null) {
                return false;
            }
            $serviceSong = $item->serviceSong;

            return $serviceSong && $serviceSong->song_id !== null && $serviceSong->song_arrangement_id === null;
        });

        foreach ($matchedSongsWithoutArrangement as $item) {
            $songName = $item->serviceSong?->cts_song_name ?? 'Unbekannter Song';
            $warnings[] = "{$songName} hat kein Arrangement ausgewählt";
        }

        // Check 3: Sermon slides
        $sermonPatterns = Setting::get('agenda_sermon_matching');

        if ($sermonPatterns) {
            // Settings configured: check if any agenda item flagged as sermon has slides
            $agendaMatcher = app(AgendaMatcherService::class);
            $sermonItems = $agendaItems->filter(function (ServiceAgendaItem $item) use ($agendaMatcher, $sermonPatterns) {
                return $agendaMatcher->matches($item->title, $sermonPatterns);
            });

            $sermonHasSlides = false;
            foreach ($sermonItems as $item) {
                if ($item->slides()->whereNull('deleted_at')->exists()) {
                    $sermonHasSlides = true;
                    break;
                }
            }

            if (! $sermonHasSlides) {
                $warnings[] = 'Keine Predigt-Folien hochgeladen';
            }
        } else {
            // No settings configured: fall back to checking slides table
            if (! $this->slides()->where('type', 'sermon')->exists()) {
                $warnings[] = 'Keine Predigt-Folien hochgeladen';
            }
        }

        return [
            'ready' => empty($warnings),
            'warnings' => $warnings,
        ];
    }

    /**
     * Legacy finalization status for services without agenda items.
     *
     * @return array{ready: bool, warnings: string[]}
     */
    private function finalizationStatusLegacy(): array
    {
        $warnings = [];

        $totalSongs = $this->serviceSongs()->count();
        $mappedSongs = $this->serviceSongs()->whereNotNull('song_id')->count();
        $arrangedSongs = $this->serviceSongs()->whereNotNull('song_arrangement_id')->count();
        $sermonSlides = $this->slides()->where('type', 'sermon')->count();

        if ($totalSongs > 0 && $mappedSongs < $totalSongs) {
            $warnings[] = "Nur {$mappedSongs} von {$totalSongs} Songs sind zugeordnet.";
        }

        if ($totalSongs > 0 && $arrangedSongs < $totalSongs) {
            $warnings[] = "Nur {$arrangedSongs} von {$totalSongs} Songs haben ein Arrangement.";
        }

        if ($sermonSlides === 0) {
            $warnings[] = 'Es wurden keine Predigtfolien hochgeladen.';
        }

        return [
            'ready' => empty($warnings),
            'warnings' => $warnings,
        ];
    }

    protected function isReadyToFinalize(): Attribute
    {
        return Attribute::get(fn () => $this->finalizationStatus()['ready']);
    }
}
