<?php

namespace App\Jobs;

use App\Models\Setting;
use App\Models\User;
use App\Models\Video;
use App\Services\NasSyncService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class NasToLocalMigrationJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries   = 1;
    public int $timeout = 7200; // 2 hours

    private function updateProgress(array $data): void
    {
        Cache::put('nas_disable_progress', json_encode($data), 3600);
    }

    public function handle(NasSyncService $nas): void
    {
        $progress = [
            'current' => 0,
            'total'   => 0,
            'phase'   => 'Counting files...',
            'done'    => false,
            'error'   => null,
        ];
        $this->updateProgress($progress);

        try {
            // ── Count all items ───────────────────────────────────────────────
            $videos = Video::where('path', 'like', 'users/%')->get();

            $slides = \DB::table('video_slides')
                ->where('filename', 'like', 'users/%')
                ->get();

            $usersWithAvatar = User::where('avatar', 'like', 'users/%')->get();
            $usersWithBanner = User::where('banner', 'like', 'users/%')->get();

            $postImages = \DB::table('post_images')
                ->where('filename', 'like', 'users/%')
                ->get();

            // Count thumbnails separately (they're additional per-video downloads)
            $videoThumbs = $videos->filter(fn($v) => $v->thumbnail && str_starts_with($v->thumbnail, 'users/'));

            $total = $videos->count()
                   + $videoThumbs->count()
                   + $slides->count()
                   + $usersWithAvatar->count()
                   + $usersWithBanner->count()
                   + $postImages->count();

            $progress['total'] = $total;
            $progress['phase'] = 'Downloading files from NAS...';
            $this->updateProgress($progress);

            // ── Download videos ───────────────────────────────────────────────
            foreach ($videos as $video) {
                $nasPath  = $video->path;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download video #' . $video->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading videos... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Download thumbnails ───────────────────────────────────────────
            foreach ($videoThumbs as $video) {
                $nasPath   = $video->thumbnail;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download thumbnail for video #' . $video->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading thumbnails... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Download slides ───────────────────────────────────────────────
            foreach ($slides as $slide) {
                $nasPath   = $slide->filename;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download slide id=' . $slide->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading audio slides... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Download user avatars ─────────────────────────────────────────
            foreach ($usersWithAvatar as $user) {
                $nasPath   = $user->avatar;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download avatar for user #' . $user->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading avatars... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Download user banners ─────────────────────────────────────────
            foreach ($usersWithBanner as $user) {
                $nasPath   = $user->banner;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download banner for user #' . $user->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading banners... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Download post images ──────────────────────────────────────────
            foreach ($postImages as $img) {
                $nasPath   = $img->filename;
                $localPath = storage_path('app/' . $nasPath);

                try {
                    $nas->ensureLocalAsset($localPath, $nasPath);
                } catch (\Throwable $e) {
                    Log::error('NasToLocalMigrationJob: failed to download post image id=' . $img->id . ' path=' . $nasPath . ': ' . $e->getMessage());
                }

                $progress['current']++;
                $progress['phase'] = 'Downloading post images... (' . $progress['current'] . '/' . $total . ')';
                $this->updateProgress($progress);
            }

            // ── Disable NAS ───────────────────────────────────────────────────
            Setting::set('nas_sync_enabled', 'false');
            app(\App\Services\NasSyncService::class)->flushReachabilityCache();

            $progress['done']  = true;
            $progress['phase'] = 'Complete';
            $this->updateProgress($progress);

            Log::info('NasToLocalMigrationJob: completed. ' . $total . ' files migrated. NAS disabled.');

        } catch (\Throwable $e) {
            Log::error('NasToLocalMigrationJob: fatal error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
            ]);

            $progress['error'] = $e->getMessage();
            $this->updateProgress($progress);
        }
    }
}
