<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Series;
use App\Models\Season;
use App\Models\Episode;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Validator;
use DataTables;

class EpisodeController extends Controller
{
    protected $user;

    public function __construct()
    {
        $this->user = Auth::guard('admin')->user();
    }

    public function index(Request $request, $seriesId, $seasonId)
    {
        if (is_null($this->user) || !$this->user->can('video.view')) {
            abort(403, 'Access Denied');
        }

        $series      = Series::findOrFail($seriesId);
        $season      = Season::where('series_id', $seriesId)->findOrFail($seasonId);
        $headerTitle = "Episodes – {$series->title} / Season {$season->season_number}";

        if ($request->ajax()) {
            $query = Episode::where('series_id', $seriesId)
                ->where('season_id', $seasonId)
                ->orderBy('episode_number');

            return DataTables::of($query)
                ->editColumn('thumbnail_image', function ($ep) {
                    return $ep->thumbnail_image
                        ? '<img src="' . asset($ep->thumbnail_image) . '" style="width:40px;height:60px;object-fit:cover">'
                        : 'N/A';
                })
                ->editColumn('video_type', function ($ep) {
                    return match ($ep->video_type) {
                        'upload'  => 'Upload',
                        'youtube' => 'YouTube',
                        'other'   => 'Other URL',
                        default   => $ep->video_type,
                    };
                })
                ->editColumn('is_premium', fn($ep) => $ep->is_premium
                    ? '<span class="badge badge-warning">Premium</span>'
                    : '<span class="badge badge-secondary">Free</span>')
                ->editColumn('status', fn($ep) => $ep->status === 0
                    ? '<span class="badge badge-success">Active</span>'
                    : '<span class="badge badge-secondary">Inactive</span>')
                ->addColumn('actions', fn($ep) => view('backend.admin.episodes.partials.actions', [
                    'episode'  => $ep,
                    'seriesId' => $seriesId,
                    'seasonId' => $seasonId,
                ])->render())
                ->rawColumns(['thumbnail_image', 'is_premium', 'status', 'actions'])
                ->make(true);
        }

        return view('backend.admin.episodes.index', compact('headerTitle', 'series', 'season'));
    }

    public function add($seriesId, $seasonId)
    {
        if (is_null($this->user) || !$this->user->can('video.create')) {
            return back()->with('error', 'Access Denied');
        }

        $series = Series::findOrFail($seriesId);
        $season = Season::where('series_id', $seriesId)->findOrFail($seasonId);

        return view('backend.admin.episodes.add', [
            'headerTitle' => 'Add Episode',
            'series'      => $series,
            'season'      => $season,
        ]);
    }

    public function insert(Request $request, $seriesId, $seasonId)
    {
        if (is_null($this->user) || !$this->user->can('video.create')) {
            abort(403, 'Access Denied');
        }

        Season::where('series_id', $seriesId)->findOrFail($seasonId);

        $validator = Validator::make($request->all(), [
            'episode_number'  => "required|integer|min:1|unique:episodes,episode_number,NULL,id,season_id,{$seasonId}",
            'title'           => 'required|string|max:255',
            'description'     => 'nullable|string',
            'thumbnail_image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg,webp|max:2048',
            'video_type'      => 'required|in:upload,youtube,other',
            'video'           => 'nullable|required_if:video_type,upload',
            'youtube_url'     => 'nullable|required_if:video_type,youtube|url|max:255',
            'other_url'       => 'nullable|required_if:video_type,other|url|max:255',
            'duration_seconds'=> 'nullable|integer|min:0',
        ], [
            'episode_number.unique' => 'This episode number already exists in the season.',
        ]);

        if ($validator->fails()) {
            return redirect()->back()->withErrors($validator)->withInput();
        }

        $thumbPath = null;
        if ($request->hasFile('thumbnail_image')) {
            $thumbPath = $this->handleUploadedFile($request->file('thumbnail_image'), 'assets/uploads/episodes/images/');
        }

        $videoPath = null;
        if ($request->video_type === 'upload' && $request->hasFile('video')) {
            $videoPath = $this->handleUploadedFile($request->file('video'), 'assets/uploads/episodes/videos/');
        }

        Episode::create([
            'series_id'        => $seriesId,
            'season_id'        => $seasonId,
            'episode_number'   => $request->episode_number,
            'title'            => $request->title,
            'description'      => $request->description,
            'thumbnail_image'  => $thumbPath,
            'video_type'       => $request->video_type,
            'youtube_url'      => $request->video_type === 'youtube' ? $request->youtube_url : null,
            'other_url'        => $request->video_type === 'other'   ? $request->other_url   : null,
            'video'            => $videoPath,
            'duration_seconds' => $request->duration_seconds ?? 0,
            'is_premium'       => $request->boolean('is_premium'),
        ]);

        return redirect("admin/series/{$seriesId}/seasons/{$seasonId}/episodes")
            ->with('success', 'Episode added successfully');
    }

    public function edit($seriesId, $seasonId, $id)
    {
        if (is_null($this->user) || !$this->user->can('video.edit')) {
            return back()->with('error', 'Access Denied');
        }

        $series  = Series::findOrFail($seriesId);
        $season  = Season::where('series_id', $seriesId)->findOrFail($seasonId);
        $episode = Episode::where('series_id', $seriesId)->where('season_id', $seasonId)->findOrFail($id);

        return view('backend.admin.episodes.edit', [
            'headerTitle' => 'Edit Episode',
            'series'      => $series,
            'season'      => $season,
            'episode'     => $episode,
        ]);
    }

    public function update(Request $request, $seriesId, $seasonId, $id)
    {
        if (is_null($this->user) || !$this->user->can('video.edit')) {
            return back()->with('error', 'Access Denied');
        }

        $episode = Episode::where('series_id', $seriesId)->where('season_id', $seasonId)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'episode_number'  => "required|integer|min:1|unique:episodes,episode_number,{$id},id,season_id,{$seasonId}",
            'title'           => 'required|string|max:255',
            'description'     => 'nullable|string',
            'thumbnail_image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg,webp|max:2048',
            'video_type'      => 'required|in:upload,youtube,other',
            'youtube_url'     => 'nullable|required_if:video_type,youtube|url|max:255',
            'other_url'       => 'nullable|required_if:video_type,other|url|max:255',
            'duration_seconds'=> 'nullable|integer|min:0',
        ], [
            'episode_number.unique' => 'This episode number already exists in the season.',
        ]);

        if ($validator->fails()) {
            return redirect()->back()->withErrors($validator)->withInput();
        }

        if ($request->hasFile('thumbnail_image')) {
            $this->deleteFile($episode->thumbnail_image);
            $episode->thumbnail_image = $this->handleUploadedFile($request->file('thumbnail_image'), 'assets/uploads/episodes/images/');
        }

        if ($request->video_type === 'upload' && $request->hasFile('video')) {
            $this->deleteFile($episode->video);
            $episode->video = $this->handleUploadedFile($request->file('video'), 'assets/uploads/episodes/videos/');
        }

        $episode->episode_number   = $request->episode_number;
        $episode->title            = $request->title;
        $episode->description      = $request->description;
        $episode->video_type       = $request->video_type;
        $episode->youtube_url      = $request->video_type === 'youtube' ? $request->youtube_url : null;
        $episode->other_url        = $request->video_type === 'other'   ? $request->other_url   : null;
        $episode->duration_seconds = $request->duration_seconds ?? 0;
        $episode->is_premium       = $request->boolean('is_premium');
        $episode->status           = $request->status ?? 0;
        $episode->save();

        return redirect("admin/series/{$seriesId}/seasons/{$seasonId}/episodes")
            ->with('success', 'Episode updated successfully');
    }

    public function delete($seriesId, $seasonId, $id)
    {
        if (is_null($this->user) || !$this->user->can('video.delete')) {
            return back()->with('error', 'Access Denied');
        }

        $episode = Episode::where('series_id', $seriesId)->where('season_id', $seasonId)->findOrFail($id);
        $this->deleteFile($episode->thumbnail_image);
        $this->deleteFile($episode->video);
        $episode->delete();

        return redirect()->back()->with('success', 'Episode deleted successfully');
    }

    // -------------------------------------------------------------------------

    private function handleUploadedFile($file, $directory)
    {
        if ($file && $file->isValid()) {
            $fileName = Str::uuid() . '.' . $file->getClientOriginalExtension();
            $file->move(public_path($directory), $fileName);
            return $directory . $fileName;
        }
        return null;
    }

    private function deleteFile($filePath)
    {
        if ($filePath && file_exists(public_path($filePath))) {
            unlink(public_path($filePath));
        }
    }
}
