<?php

namespace App\Http\Controllers\Api\Platform;

use App\Enums\PostStepEnum;
use App\Http\Controllers\Controller;
use App\Libs\Upload\ChunkUploadManager;
use App\Libs\Upload\UploadPostAttachments;
use App\Models\PostComment;
use App\Models\Like;
use App\Models\Post;
use App\Models\Save;
use App\RequestRules\Api\PostRules;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\UploadedFile;

class PostController extends Controller
{
   /**
    * Add goods products
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function createPost(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::creationRules());

      if ($request->{"step"} == PostStepEnum::create->value) {
         try {
            /** @var ?Post $post */
            $post = Post::createPost($request->all());

            if ($post !== null) {
               $post = $post->commonSerialization();

               return api_response(100, "Okay", $post);
            }
         } catch (\Exception $exception) {
            log_debug($exception, "PostController::createPost");
         }
      }

      if ($request->{"step"} == PostStepEnum::attachments->value) {
         try {
            /** @var Post $post */
            $post = Post::findById($request->{'post_id'});

            $chunkManager = new ChunkUploadManager(
               requestKey: "attachment",
            );

            // Try to upload file into chunk mode
            $uploadedFile = $chunkManager->upload($request);

            if ($uploadedFile instanceof UploadedFile) {
               $result = UploadPostAttachments::uploadAttachments($post, $uploadedFile);

               if (filled($result)) {
                  $post = $post->refresh()->commonSerialization();

                  return api_response(100, "Okay", $post);
               }
            }
         } catch (\Exception $exception) {
            log_debug($exception, "PostController::createPost");
         }
      }

      return api_response(120, __('errors.unknown_error'));
   }

   /**
    * Republish post
    *
    * @param Request $request
    * @return Response|Application|ResponseFactory
    */
   public function republish(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::repostRules());

      try {
         /** @var Post $post */
         $post = Post::findById($request->{'post_id'});
         $post = $post->republish();

         return api_response(100, "Okay", $post->commonSerialization());
      } catch (\Exception $exception) {
         log_debug($exception, "PostController::republish");
      }

      return api_response(120, __('errors.unknown_error'));
   }

   /**
    * Get feed posts
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function postFeeds(Request $request): Response|Application|ResponseFactory
   {
      try {
         $postFeeds = Post::getPostFeeds($request->get("page"));
         $businessPosts = Post::getPostFeeds($request->get("page"), true);

         $finalData = array(
            "posts_feed" => Post::buildPostsPaginator($postFeeds),
            "business_posts_feed" => Post::buildPostsPaginator($businessPosts),
         );

         return api_response(100, "Okay", $finalData);
      } catch (\Exception $exception) {
         log_debug($exception, "PostController::postFeeds");
      }

      return api_response(120, __("errors.unknown_error"));
   }

   /**
    * Like/Unlike post
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function likePost(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::likePost());

      /** @var ?Post $likePost */
      $likePost = Like::likePost($request->get("post_id"));

      if ($likePost == null) {
         return api_response(120, __("errors.unknown_error"));
      }

      return api_response(100, "Okay", $likePost->commonSerialization());
   }

   /**
    * Save/UnSave post
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function savePost(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::savePost());

      /** @var ?Post $savedPost */
      $savedPost = Save::savePost($request->all());

      if ($savedPost == null) {
         return api_response(120, __("errors.unknown_error"));
      }

      return api_response(
         100,
         "Okay",
         $savedPost->commonSerialization()
      );
   }

   /**
    * Share/UnShare post
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function sharePost(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::sharePost());

      /** @var Post $post */
      $post = Post::findById($request->{'post_id'});
      $shareAction = $post->shareToAnother($request->all());

      if ($shareAction == null) {
         return api_response(120, __("errors.unknown_error"));
      }

      return api_response(100, "Okay");
   }

   /**
    * Create post comment
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function commentPost(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::commentPost());

      $replyTo = null;

      if (filled($request->{'post_comment_id'})) {
         /** @var PostComment $replyTo */
         $replyTo = PostComment::findById($request->{'post_comment_id'});

         $postComment = $replyTo->commentReply($request->all());
      } else {
         $postComment = PostComment::commentPost($request->all());
      }

      if ($postComment == null) {
         return api_response(120, __("errors.unknown_error"));
      }

      $postComment = $replyTo ?? $postComment;
      $result = $postComment->computeCommentDetails();
      $result['answers'] = $postComment->getAnswers(page: 1);

      return api_response(100, "Okay", $result);
   }

   /**
    * Reply comment
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function commentReply(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::commentReply());

      /** @var PostComment $comment */
      $comment = PostComment::findById($request->{'post_comment_id'});

      // Reply
      $commentReply = $comment->commentReply($request->all());
      if ($commentReply == null) {
         return api_response(120, __("errors.unknown_error"));
      }

      $result = $comment->computeCommentDetails();
      $result['answers'] = $comment->getAnswers(page: 1);

      return api_response(100, "Okay", $result);
   }

   /**
    * Get post comments
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function postComments(Request $request): Response|Application|ResponseFactory
   {
      try {
         $postComments = PostComment::getCommentPost($request->{"postId"}, $request->{"page"});

         $postCommentArray = array();
         foreach ($postComments as $comment) {
            $commentResult = $comment->computeCommentDetails();
            $commentResult['answers'] = $comment->getAnswers(page: 1);

            $postCommentArray[] = $commentResult;
         }

         $finalData = default_paginator_format(
            $postComments->lastPage(),
            $postComments->total(),
            $postComments->currentPage(),
            "comments",
            $postCommentArray,
         );

         return api_response(100, "Okay", $finalData);

      } catch (\Exception $exception) {
         log_debug($exception, "UserController::followers");
      }

      return api_response(120, __("errors.unknown_error"));
   }

   /**
    * Turn on comment
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function turnOnComment(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(PostRules::turnOnComment());

      /** @var Post $post */
      $post = Post::findById($request->{"post_id"});

      $post->turnOnComment();

      return api_response(100, "Okay");
   }

   /**
    * Delete post
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function deletePost(Request $request): Response|Application|ResponseFactory
   {
      /** @var ?Post $post */
      $post = Post::findById($request->{"post_id"});

      if ($post == null) {
         return api_response(101, __("errors.unknown_post"));
      }

      $post->deletePOst();
      return api_response(100, "Okay");
   }

   /**
    * Get post details
    *
    * @param int $postId
    * @return Application|ResponseFactory|Response
    */
   public function postDetails(int $postId): Response|Application|ResponseFactory
   {
      /** @var ?Post $post */
      $post = Post::findById($postId);

      if ($post == null) {
         return api_response(101, __("errors.unknown_post"));
      }

      return api_response(100, "Okay", $post->commonSerialization());
   }
}
