<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\ImportJob;
use App\Models\Episode;
use App\Models\Season;
use App\Models\Subtitle;
use App\Models\VideoSource;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ImportController extends Controller
{
    public function index()
    {
        $jobs = ImportJob::latest()->paginate(20);

        // Araçlar paneli için istatistikler
        $stats = [
            'total_animes'          => \App\Models\Anime::where('is_published', true)->count(),
            'anizium_done'          => ImportJob::where('source', 'anizium')->where('status', 'done')->count(),
            'animecix_done'         => ImportJob::where('source', 'animecix')->where('status', 'done')->count(),
            'video_sources_total'   => VideoSource::count(),
            'anizium_sources'       => VideoSource::where('source', 'anizium')->count(),
            'animecix_sources'      => VideoSource::where('source', 'animecix')->count(),
            'subtitle_mismatch'     => $this->countSubtitleMismatch(),
        ];

        return view('admin.import.index', compact('jobs', 'stats'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'source_url'       => 'required|url|max:500',
            'cdn_id'           => 'nullable|string|max:50',
            'anime_title'      => 'nullable|string|max:255',
            'season_ranges'    => 'nullable|array',
            'season_ranges.*.season' => 'required_with:season_ranges|integer|min:1',
            'season_ranges.*.from'   => 'required_with:season_ranges|integer|min:1',
            'season_ranges.*.to'     => 'required_with:season_ranges|integer|min:1',
        ]);

        $watchId = null;
        if ($request->source_url) {
            preg_match('/\/(?:anime|watch)\/(\d+)/', $request->source_url, $m);
            $watchId = $m[1] ?? null;
        }

        $ranges = null;
        if ($request->filled('season_ranges')) {
            $ranges = [];
            foreach ($request->season_ranges as $r) {
                if (empty($r['season']) || empty($r['from']) || empty($r['to'])) continue;
                $from = (int) $r['from'];
                $to   = (int) $r['to'];
                if ($from > $to) [$from, $to] = [$to, $from];
                $ranges[] = ['season' => (int)$r['season'], 'from' => $from, 'to' => $to];
            }
            if (empty($ranges)) $ranges = null;
        }

        $job = ImportJob::create([
            'source_url'    => $request->source_url,
            'watch_id'      => $watchId,
            'cdn_id'        => $request->cdn_id ? trim($request->cdn_id) : null,
            'anime_title'   => $request->anime_title,
            'season_ranges' => $ranges,
            'status'        => 'pending',
        ]);

        return redirect()->route('admin.import.show', $job)
            ->with('success', "Import job #{$job->id} oluşturuldu. Python script'i başlatın.");
    }

    public function show(ImportJob $import)
    {
        return view('admin.import.show', compact('import'));
    }

    public function destroy(ImportJob $import)
    {
        $import->delete();
        return redirect()->route('admin.import.index')->with('success', 'Job silindi.');
    }

    public function destroyFailed()
    {
        $count = ImportJob::where('status', 'failed')->count();
        ImportJob::where('status', 'failed')->delete();
        return redirect()->route('admin.import.index')->with('success', "{$count} hatalı job silindi.");
    }

    public function destroyPending()
    {
        $count = ImportJob::where('status', 'pending')->count();
        ImportJob::where('status', 'pending')->delete();
        return redirect()->route('admin.import.index')->with('success', "{$count} bekleyen job silindi.");
    }

    public function destroyStuck()
    {
        // fetching/downloading/uploading ama 2 saatten fazladır güncellenmemiş = takılı kalmış
        $cutoff = now()->subHours(2);
        $count = ImportJob::whereIn('status', ['fetching', 'downloading', 'uploading'])
            ->where('updated_at', '<', $cutoff)
            ->count();
        ImportJob::whereIn('status', ['fetching', 'downloading', 'uploading'])
            ->where('updated_at', '<', $cutoff)
            ->delete();
        return redirect()->route('admin.import.index')->with('success', "{$count} takılı kalmış job silindi.");
    }

    public function bulkCounts()
    {
        $cutoff = now()->subHours(2);
        return response()->json([
            'failed'  => ImportJob::where('status', 'failed')->count(),
            'pending' => ImportJob::where('status', 'pending')->count(),
            'stuck'   => ImportJob::whereIn('status', ['fetching', 'downloading', 'uploading'])
                             ->where('updated_at', '<', $cutoff)
                             ->count(),
        ]);
    }

    public function destroyByStatus(Request $request)
    {
        $statuses = $request->input('statuses', []);
        $hours    = (int) $request->input('stuck_hours', 2);

        $allowed = ['pending', 'failed', 'fetching', 'downloading', 'uploading'];
        $statuses = array_intersect($statuses, $allowed);

        if (empty($statuses)) {
            return response()->json(['ok' => false, 'message' => 'Geçerli status seçilmedi.'], 422);
        }

        $query = ImportJob::whereIn('status', $statuses);

        // Aktif statüler için sadece belirtilen saatten eskilerini sil
        $activeStatuses = array_intersect($statuses, ['fetching', 'downloading', 'uploading']);
        if (!empty($activeStatuses) && count($activeStatuses) === count($statuses)) {
            $query->where('updated_at', '<', now()->subHours($hours));
        }

        $count = $query->count();
        $query->delete();

        return response()->json(['ok' => true, 'deleted' => $count]);
    }

    // ── ARAÇLAR: Terminal gerektirmez, admin panelden çalışır ─────────────────

    /**
     * Altyazı uyuşmazlığı düzelt (Anizium episode-1 cache bug).
     * Subtitle URL'sindeki name=s1_b1_XX yanlış bölümü işaret edenleri siler.
     */
    public function fixSubtitles(Request $request)
    {
        $dryRun  = $request->boolean('dry_run', false);
        $animeId = $request->input('anime_id');

        $query = Subtitle::query()
            ->join('episodes', 'subtitles.episode_id', '=', 'episodes.id')
            ->join('seasons',  'seasons.id',           '=', 'episodes.season_id')
            ->whereNotNull('subtitles.url')
            ->where('subtitles.url', 'like', '%anizium%')
            ->select(
                'subtitles.id as subtitle_id',
                'subtitles.language',
                'subtitles.url',
                'seasons.season_number',
                'episodes.episode_number',
                'episodes.anime_id',
            );

        if ($animeId) {
            $query->where('episodes.anime_id', (int) $animeId);
        }

        $subtitles   = $query->get();
        $mismatchIds = [];
        $details     = [];

        foreach ($subtitles as $sub) {
            $parsed = parse_url($sub->url);
            if (!isset($parsed['query'])) continue;
            parse_str($parsed['query'], $params);
            $name = $params['name'] ?? '';
            if (!$name) continue;

            $expectedPrefix = "s{$sub->season_number}_b{$sub->episode_number}_";
            if (!str_starts_with($name, $expectedPrefix)) {
                $mismatchIds[] = $sub->subtitle_id;
                $details[] = [
                    'anime_id' => $sub->anime_id,
                    'season'   => $sub->season_number,
                    'episode'  => $sub->episode_number,
                    'lang'     => $sub->language,
                    'name'     => $name,
                    'expected' => $expectedPrefix . $sub->language,
                ];
            }
        }

        $deleted = 0;
        if (!$dryRun && !empty($mismatchIds)) {
            $deleted = Subtitle::whereIn('id', $mismatchIds)->delete();
        }

        return response()->json([
            'ok'           => true,
            'dry_run'      => $dryRun,
            'checked'      => $subtitles->count(),
            'mismatch'     => count($mismatchIds),
            'deleted'      => $deleted,
            'details'      => array_slice($details, 0, 30),
        ]);
    }

    /**
     * Anizium done job'larını yeniden pending yap (yeni video_sources eklemek için).
     * Her job'ın done_episodes sıfırlanır; Anizium bot yeniden çalışınca
     * doneEpisodes() artık source='anizium' kontrolü yaptığından
     * sadece video_sources'ta anizium kaydı OLMAYAN bölümleri yeniden işler.
     */
    public function requeueAnizium(Request $request)
    {
        $limit   = (int) $request->input('limit', 50);
        $animeId = $request->input('anime_id');

        $query = ImportJob::where('source', 'anizium')
            ->where('status', 'done')
            ->whereNotNull('watch_id')
            ->latest();

        if ($animeId) {
            $query->where('anime_id', (int) $animeId);
        }

        $jobs    = $query->limit($limit)->get();
        $requeued = 0;

        foreach ($jobs as $job) {
            // Zaten pending/işleniyor olan var mı?
            $active = ImportJob::where('watch_id', $job->watch_id)
                ->where('source', 'anizium')
                ->whereIn('status', ['pending', 'fetching', 'downloading', 'uploading'])
                ->exists();

            if (!$active) {
                $job->update([
                    'status'       => 'pending',
                    'done_episodes'=> 0,
                    'error_log'    => null,
                    'current_step' => 'Çapraz re-import — video_sources yenileme',
                ]);
                $requeued++;
            }
        }

        return response()->json([
            'ok'       => true,
            'checked'  => $jobs->count(),
            'requeued' => $requeued,
        ]);
    }

    /**
     * AnimeCix done job'larını yeniden pending yap.
     */
    public function requeueAnimecix(Request $request)
    {
        $limit   = (int) $request->input('limit', 50);
        $animeId = $request->input('anime_id');

        $query = ImportJob::where('source', 'animecix')
            ->where('status', 'done')
            ->whereNotNull('animecix_title_id')
            ->latest();

        if ($animeId) {
            $query->where('anime_id', (int) $animeId);
        }

        $jobs     = $query->limit($limit)->get();
        $requeued = 0;

        foreach ($jobs as $job) {
            $active = ImportJob::where('animecix_title_id', $job->animecix_title_id)
                ->where('source', 'animecix')
                ->whereIn('status', ['pending', 'fetching'])
                ->exists();

            if (!$active) {
                $job->update([
                    'status'       => 'pending',
                    'done_episodes'=> 0,
                    'error_log'    => null,
                    'current_step' => 'Çapraz re-import — video_sources yenileme',
                ]);
                $requeued++;
            }
        }

        return response()->json([
            'ok'       => true,
            'checked'  => $jobs->count(),
            'requeued' => $requeued,
        ]);
    }

    /**
     * video_sources istatistikleri (AJAX için).
     */
    public function sourceStats()
    {
        $animeCount = \App\Models\Anime::where('is_published', true)->count();

        $episodesWithBoth = DB::table('episodes')
            ->whereExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'anizium'))
            ->whereExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'animecix'))
            ->where('is_published', true)
            ->count();

        $episodesOnlyAnizium = DB::table('episodes')
            ->whereExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'anizium'))
            ->whereNotExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'animecix'))
            ->where('is_published', true)
            ->count();

        $episodesOnlyAnimecix = DB::table('episodes')
            ->whereExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'animecix'))
            ->whereNotExists(fn($q) => $q->from('video_sources')->whereColumn('video_sources.episode_id', 'episodes.id')->where('video_sources.source', 'anizium'))
            ->where('is_published', true)
            ->count();

        return response()->json([
            'anime_count'              => $animeCount,
            'episodes_with_both'       => $episodesWithBoth,
            'episodes_only_anizium'    => $episodesOnlyAnizium,
            'episodes_only_animecix'   => $episodesOnlyAnimecix,
            'subtitle_mismatch'        => $this->countSubtitleMismatch(),
            'anizium_pending_jobs'     => ImportJob::where('source', 'anizium')->where('status', 'pending')->count(),
            'animecix_pending_jobs'    => ImportJob::where('source', 'animecix')->where('status', 'pending')->count(),
        ]);
    }

    // ── Yardımcı ─────────────────────────────────────────────────────────────

    private function countSubtitleMismatch(): int
    {
        $rows = Subtitle::query()
            ->join('episodes', 'subtitles.episode_id', '=', 'episodes.id')
            ->join('seasons',  'seasons.id',           '=', 'episodes.season_id')
            ->whereNotNull('subtitles.url')
            ->where('subtitles.url', 'like', '%anizium%')
            ->select('subtitles.url', 'seasons.season_number', 'episodes.episode_number')
            ->get();

        $count = 0;
        foreach ($rows as $r) {
            $parsed = parse_url($r->url);
            if (!isset($parsed['query'])) continue;
            parse_str($parsed['query'], $params);
            $name = $params['name'] ?? '';
            if ($name && !str_starts_with($name, "s{$r->season_number}_b{$r->episode_number}_")) {
                $count++;
            }
        }
        return $count;
    }
}
