<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;
use Throwable;

class RigPlaylistCommand extends Command
{
    protected $signature = 'rig:playlist';
    protected $description = 'Index audio under the configured music roots → storage/data/playlist.json';

    private const EXTS = ['m4a', 'mp3', 'opus', 'ogg', 'flac', 'webm', 'aac', 'wav'];

    public function handle(): int
    {
        $roots = array_values(array_filter((array) config('rig.music_dirs')));
        if (empty($roots)) {
            $this->warn('  ! no music dirs configured (set MUSIC_DIR_1 in .env)');
        }

        $ffprobe = (string) config('rig.ffprobe', '/usr/bin/ffprobe');
        if (!is_executable($ffprobe)) {
            $this->error("  ✗ ffprobe not found at {$ffprobe} (install ffmpeg or set FFPROBE_BIN)");
            return self::FAILURE;
        }

        $this->line('── Indexing audio roots ──');
        foreach ($roots as $r) {
            $this->line(is_dir($r) ? "    + {$r}" : "    ! {$r} (missing — skipped)");
        }

        $tracks = [];
        foreach ($roots as $root) {
            if (!is_dir($root)) continue;
            $finder = (new Finder())
                ->files()
                ->in($root)
                ->name('/\.(' . implode('|', self::EXTS) . ')$/i')
                ->ignoreUnreadableDirs()
                ->sortByName();

            foreach ($finder as $file) {
                $name = $file->getFilename();
                $base = $file->getFilenameWithoutExtension();
                // Skip yt-dlp intermediates (e.g. foo.f140.m4a, foo.temp.opus).
                if (preg_match('/\.(?:f\d+|temp|part)$/i', $base)) continue;

                $path = $file->getRealPath();
                $meta = $this->probe($ffprobe, $path);
                $tracks[] = [
                    'title'       => $this->cleanTitle($base),
                    'file'        => 'file://' . $this->urlEncodePath($path),
                    'durationSec' => isset($meta['durationSec']) ? (int) $meta['durationSec'] : null,
                ];
            }
        }

        $doc = [
            'syncedAt'   => gmdate('Y-m-d\TH:i:s\Z'),
            'sourceDirs' => $roots,
            'trackCount' => count($tracks),
            'tracks'     => $tracks,
        ];
        $path = rtrim(config('rig.storage_data'), '/') . '/playlist.json';
        @mkdir(dirname($path), 0775, true);
        file_put_contents(
            $path,
            json_encode($doc, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
        );

        $this->line('');
        $this->info("  ✓ wrote {$path} ({$doc['trackCount']} tracks)");
        $this->line('  → refresh the Music Daemon browser source in OBS to reload the queue.');
        return self::SUCCESS;
    }

    private function probe(string $ffprobe, string $path): array
    {
        try {
            $proc = new Process([
                $ffprobe, '-v', 'error',
                '-show_entries', 'format=duration:format_tags=title,artist',
                '-of', 'json',
                $path,
            ]);
            $proc->setTimeout(10);
            $proc->run();
            if (!$proc->isSuccessful()) return [];
            $json = json_decode($proc->getOutput(), true) ?: [];
            $fmt = $json['format'] ?? [];
            return [
                'durationSec' => isset($fmt['duration']) ? (float) $fmt['duration'] : null,
            ];
        } catch (Throwable) {
            return [];
        }
    }

    /**
     * Mirrors scripts/playlist.sh's clean_title():
     *  - drop "| ..." (or fullwidth ｜) tails (genre/label noise)
     *  - strip trailing YouTube IDs in brackets like "[-XxZTgMWKV0]"
     *  - strip "[NCS Release]" / "(NCS10 Release)" suffixes
     */
    private function cleanTitle(string $t): string
    {
        $t = preg_replace('/\s*[｜|].*$/u', '', $t) ?? $t;
        $t = preg_replace('/\s*\[[A-Za-z0-9_-]{11}\]\s*$/', '', $t) ?? $t;
        $t = preg_replace(
            '/\s*[\[(](?:NCS\d*|No Copyright Sounds)(?:\s+Release)?[\])]\s*$/i',
            '',
            $t
        ) ?? $t;
        return trim($t);
    }

    private function urlEncodePath(string $path): string
    {
        // Same as Python's urllib.parse.quote(..., safe='/') — keep separators, encode the rest.
        return implode('/', array_map('rawurlencode', explode('/', $path)));
    }
}
