<?php

namespace App\Services;

use App\Helpers\EntryHelpers;
use App\Jobs\CreateXenForoCommentsThread;
use App\Models\Entry;
use App\Models\News;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class NewsService
{
    /**
     * Request for store/edit.
     * @var Request|null
     */
    private ?Request $request = null;

    /**
     * Entry for edit.
     * @var News|null
     */
    private ?News $news = null;


    public function storeNews(Request $request): News
    {
        $this->request = $request;
        $user_id = \Auth::user()->user_id;

        $news = DB::transaction(function () use ($user_id) {

            // STEP 1 : Slug
            $slug = EntryHelpers::uniqueSlug( $this->request->input('title'), News::class );

            $fields = [
                'title' => $this->request->input('title'),
                'slug' => $slug,
                'category_id' => $this->request->input('category'),
                'description' => $this->request->input('description'),
                'state' => $this->request->input('submit-state'),
                'entry_id' => $this->request->input('entry_id'),
                'relevant_link' => $this->request->input('release_site'),
                'youtube_link' => $this->request->input('youtube_link'),
                'user_id' => $user_id,
            ];

            $news = News::create( $fields );

            // STEP 3 : Prepare Gallery images.
            $this->Step3a_PrepareGalleryImages( $news );

            return $news;

        });

        $this->Step3b_SaveGalleryImages( $news );

        $this->Step4_CreateCommentsThread( $news );

        return $news;
    }

    private function Step3a_PrepareGalleryImages(News $news): void
    {
        foreach( $this->request->input('gallery', [] ) ?? [] as $i => $imagePath ){
            $news->gallery()->create([
                'image' => $imagePath,
                'order' => $i
            ]);
        }
    }

    private function Step3b_SaveGalleryImages(News $news): void
    {
        foreach ( $news->gallery ?? [] as $galleryItem ) {
            $newPath = 'news/gallery-images/' . $news->id . '/' . basename($galleryItem->image);

            if( !Storage::disk('public')->move($galleryItem->image, $newPath) )
                continue;

            $galleryItem->update(['image' => $newPath]);
        }
    }

    private function Step4_CreateCommentsThread( News $news ): void
    {
        if( $news->state !== 'published' )
            return;

        if( !$news->comments_thread_id )
            CreateXenForoCommentsThread::dispatch( $news );
    }

    public function editNews(Request $request, News $news): News
    {
        $this->request = $request;
        $this->news = $news;

        if( \Auth::user()->can('moderate', $news) ){
            $user_id = $this->request->input('owner_user_id');
        } else {
            $user_id = \Auth::user()->user_id;
        }

        $galleryPaths = [];

        $news = DB::transaction(function () use ($user_id, &$galleryPaths) {

            // STEP 1 : Refresh slug.
            if( $this->request->input('title') !== $this->news->title ){
                $this->news->slug = EntryHelpers::uniqueSlug( $this->request->input('title'), News::class, $this->news->id );
            }

            $fields = [
                'title' => $this->request->input('title'),
                'slug' => $this->news->slug,
                'category_id' => $this->request->input('category'),
                'description' => $this->request->input('description'),
                'state' => $this->request->input('submit-state'),
                'entry_id' => $this->request->input('entry_id'),
                'relevant_link' => $this->request->input('release_site'),
                'youtube_link' => $this->request->input('youtube_link'),
                'user_id' => $user_id,
            ];

            if( \Auth::user()->can('moderate', $this->news) ){
                $fields['staff_comment'] = $this->request->input('staff_comment');
                $fields['comments_thread_id'] = $this->request->input('comments_thread_id');
            }

            $this->news->update( $fields );

            $galleryPaths = $this->eStep3a_UpdateGalleryImages();

            return $this->news;

        });

        $this->eStep3b_UpdateGalleryImages( $galleryPaths );

        $this->step4_CreateCommentsThread( $news );

        return $news;

    }

    private function eStep3a_UpdateGalleryImages(): array
    {
        $requestGallery = $this->request->input('gallery', [] ) ?? [];
        $existingGalleryPaths = $this->news->gallery->pluck('image')->toArray();

        $needDeletion = array_diff( $existingGalleryPaths, $requestGallery );

        if( !empty( $needDeletion ) ){
            $this->news->gallery()->whereIn('image', $needDeletion )->delete();
        }

        $needAddition = array_diff( $requestGallery, $existingGalleryPaths );
        $images = [];
        foreach( $needAddition as $imagePath ){
            $images[] = $this->news->gallery()->create([
                'image' => $imagePath,
            ]);
        }

        foreach( $requestGallery as $i => $imagePath ){
            $this->news->gallery()->where('image', $imagePath )->update(['order' => $i]);
        }

        return [ 'addition' => $images, 'deletion' => $needDeletion ];
    }

    private function eStep3b_UpdateGalleryImages( array $pathsChanges ): void
    {
        foreach ( $pathsChanges['deletion'] as $deletePath ){
            if( Storage::disk('public')->exists($deletePath) )
                Storage::disk('public')->delete($deletePath);
        }

        foreach ( $pathsChanges['addition'] as $galleryItem ){
            $newPath = 'news/gallery-images/' . $this->news->id . '/' . basename( $galleryItem->image );

            if( !Storage::disk('public')->move( $galleryItem->image, $newPath ) ){
                continue;
            }

            $galleryItem->update(['image' => $newPath]);
        }
    }

}
