<?php

namespace App\Http\Controllers\Admin;

use App\Album;
use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Http\Controllers\Controller;
use App\Mail\PhotoCommentApproved;
use App\Mail\PhotoCommentApprovedUser;
use App\Mail\PhotoCommentRepliedTo;
use App\Photo;
use App\PhotoComment;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\View;

class PhotoCommentController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        View::share('is_admin', true);
    }

    public function applyBulkAction(Request $request)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $commentIDs = $request->get('comment_ids');
        if (is_null($commentIDs) || !is_array($commentIDs) || count($commentIDs) == 0)
        {
            $request->session()->flash('warning', trans('admin.no_comments_selected_message'));
            return redirect(route('comments.index'));
        }

        $comments = PhotoComment::whereIn('id', $commentIDs)->get();
        $commentsActioned = 0;

        if ($request->has('bulk_delete'))
        {
            /** @var PhotoComment $comment */
            foreach ($comments as $comment)
            {
                $comment->delete();
                $commentsActioned++;
            }

            $request->session()->flash('success', trans_choice('admin.bulk_comments_deleted', $commentsActioned, ['number' => $commentsActioned]));
        }
        else if ($request->has('bulk_approve'))
        {
            /** @var PhotoComment $comment */
            foreach ($comments as $comment)
            {
                if ($comment->isApproved())
                {
                    // Don't make changes if already approved
                    continue;
                }

                // Mark as approved
                $comment->approved_at = new \DateTime();
                $comment->approved_user_id = $this->getUser()->id;

                // The comment may have already been rejected - remove the data if so
                $comment->rejected_at = null;
                $comment->rejected_user_id = null;

                // Send the notification e-mail to the owner

                $comment->save();
                $commentsActioned++;

                // Send e-mail notification
                $photo = $comment->photo;
                $album = $photo->album;
                $this->notifyAlbumOwnerAndPoster($album, $photo, $comment);
            }

            $request->session()->flash('success', trans_choice('admin.bulk_comments_approved', $commentsActioned, ['number' => $commentsActioned]));
        }
        else if ($request->has('bulk_reject'))
        {
            /** @var PhotoComment $comment */
            foreach ($comments as $comment)
            {
                if ($comment->isRejected())
                {
                    // Don't make changes if already rejected
                    continue;
                }

                // Mark as rejected
                $comment->rejected_at = new \DateTime();
                $comment->rejected_user_id = $this->getUser()->id;

                // The comment may have already been approved - remove the data if so
                $comment->approved_at = null;
                $comment->approved_user_id = null;

                $comment->save();
                $commentsActioned++;
            }

            $request->session()->flash('success', trans_choice('admin.bulk_comments_approved', $commentsActioned, ['number' => $commentsActioned]));
        }

        return redirect(route('comments.index'));
    }

    public function approve($id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $comment = $this->loadCommentByID($id);

        return Theme::render('admin.approve_comment', ['comment' => $comment]);
    }

    public function bulkAction(Request $request)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $commentIDs = $request->get('comment_ids');
        if (is_null($commentIDs) || !is_array($commentIDs) || count($commentIDs) == 0)
        {
            $request->session()->flash('warning', trans('admin.no_comments_selected_message'));
            return redirect(route('comments.index'));
        }

        if ($request->has('bulk_delete'))
        {
            if (count($commentIDs) == 1)
            {
                // Single comment selected - redirect to the single delete page
                return redirect(route('comments.delete', ['id' => $commentIDs[0]]));
            }

            // Show the view to confirm the delete
            return Theme::render('admin.bulk_delete_comments', [
                'comment_count' => count($commentIDs),
                'comment_ids' => $commentIDs
            ]);
        }
        else if ($request->has('bulk_approve'))
        {
            if (count($commentIDs) == 1)
            {
                // Single comment selected - redirect to the single approve page
                return redirect(route('comments.approve', ['id' => $commentIDs[0]]));
            }

            // Show the view to confirm the approval
            return Theme::render('admin.bulk_approve_comments', [
                'comment_count' => count($commentIDs),
                'comment_ids' => $commentIDs
            ]);
        }
        else if ($request->has('bulk_reject'))
        {
            if (count($commentIDs) == 1)
            {
                // Single comment selected - redirect to the single reject page
                return redirect(route('comments.reject', ['id' => $commentIDs[0]]));
            }

            // Show the view to confirm the rejection
            return Theme::render('admin.bulk_reject_comments', [
                'comment_count' => count($commentIDs),
                'comment_ids' => $commentIDs
            ]);
        }

        // Unrecognised action - simply redirect back to the index page
        return redirect(route('comments.index'));
    }

    public function confirmApprove(Request $request, $id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $comment = $this->loadCommentByID($id);

        if ($comment->isApproved())
        {
            // Comment has already been approved
            return redirect(route('comments.index'));
        }

        // Mark as approved
        $comment->approved_at = new \DateTime();
        $comment->approved_user_id = $this->getUser()->id;

        // The comment may have already been rejected - remove the data if so
        $comment->rejected_at = null;
        $comment->rejected_user_id = null;

        $comment->save();

        $request->session()->flash('success', trans('admin.comment_approval_successful', [
            'author_name' => $comment->authorDisplayName()
        ]));

        // Send e-mail notification
        $photo = $comment->photo;
        $album = $photo->album;
        $this->notifyAlbumOwnerAndPoster($album, $photo, $comment);

        return redirect(route('comments.index'));
    }

    public function confirmReject(Request $request, $id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $comment = $this->loadCommentByID($id);

        if ($comment->isRejected())
        {
            // Comment has already been rejected
            return redirect(route('comments.index'));
        }

        // Mark as rejected
        $comment->rejected_at = new \DateTime();
        $comment->rejected_user_id = $this->getUser()->id;

        // The comment may have already been approved - remove the data if so
        $comment->approved_at = null;
        $comment->approved_user_id = null;

        $comment->save();

        $request->session()->flash('success', trans('admin.comment_rejection_successful', [
            'author_name' => $comment->authorDisplayName()
        ]));

        return redirect(route('comments.index'));
    }

    public function delete($id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $comment = $this->loadCommentByID($id);

        return Theme::render('admin.delete_comment', ['comment' => $comment]);
    }

    public function destroy(Request $request, $id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        /** @var PhotoComment $comment */
        $comment = $this->loadCommentByID($id);

        $comment->delete();
        $request->session()->flash('success', trans('admin.comment_deletion_successful', [
            'author_name' => $comment->authorDisplayName()
        ]));

        return redirect(route('comments.index'));
    }

    public function index(Request $request)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $validStatusList = [
            'all',
            'pending',
            'approved',
            'rejected'
        ];

        $filterStatus = $request->get('status', 'all');
        if (!in_array($filterStatus, $validStatusList))
        {
            $filterStatus = $validStatusList[0];
        }

        $comments = PhotoComment::with('photo')
            ->with('photo.album')
            ->orderBy('created_at', 'desc');

        switch (strtolower($filterStatus))
        {
            case 'approved':
                $comments->whereNotNull('approved_at')
                    ->whereNull('rejected_at');
                break;

            case 'pending':
                $comments->whereNull('approved_at')
                    ->whereNull('rejected_at');
                break;

            case 'rejected':
                $comments->whereNull('approved_at')
                    ->whereNotNull('rejected_at');
                break;
        }

        return Theme::render('admin.list_comments', [
            'comments' => $comments->paginate(UserConfig::get('items_per_page')),
            'filter_status' => $filterStatus,
            'success' => $request->session()->get('success'),
            'warning' => $request->session()->get('warning')
        ]);
    }

    public function reject($id)
    {
        $this->authorizeAccessToAdminPanel('admin:manage-comments');

        $comment = $this->loadCommentByID($id);

        return Theme::render('admin.reject_comment', ['comment' => $comment]);
    }

    /**
     * Loads a given comment by its ID.
     * @param $id
     * @return PhotoComment
     */
    private function loadCommentByID($id)
    {
        $comment = PhotoComment::where('id', intval($id))->first();
        if (is_null($comment))
        {
            App::abort(404);
        }

        return $comment;
    }

    /**
     * Sends an e-mail notification to an album's owned that a comment has been posted/approved.
     * @param Album $album
     * @param Photo $photo
     * @param PhotoComment $comment
     */
    private function notifyAlbumOwnerAndPoster(Album $album, Photo $photo, PhotoComment $comment)
    {
        $owner = $album->user;

        Mail::to($owner)->send(new PhotoCommentApproved($owner, $album, $photo, $comment));

        // Also send a notification to the comment poster
        $poster = new User();
        $poster->name = $comment->authorDisplayName();
        $poster->email = $comment->authorEmail();

        Mail::to($poster)->send(new PhotoCommentApprovedUser($poster, $album, $photo, $comment));

        // Send notification to the parent comment owner (if this is a reply)
        if (!is_null($comment->parent_comment_id))
        {
            $parentComment = $this->loadCommentByID($comment->parent_comment_id);

            if (is_null($parentComment))
            {
                return;
            }

            $parentPoster = new User();
            $parentPoster->name = $parentComment->authorDisplayName();
            $parentPoster->email = $parentComment->authorEmail();

            Mail::to($parentPoster)->send(new PhotoCommentRepliedTo($parentPoster, $album, $photo, $comment));
        }
    }
}