<?php

namespace App\Http\Controllers\Api\Platform;

use App\Exceptions\InvalidDeletingPrimaryTelephoneAttempt;
use App\Exceptions\InvalidEditingPrimaryTelephoneAttempt;
use App\Exceptions\InvalidNumberDeactivationAttempt;
use App\Exceptions\InvalidPasswordException;
use App\Exceptions\InvalidTelephone;
use App\Exceptions\TelephoneAlreadyExistException;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\UserTelephone;
use App\RequestRules\Api\UserTelephoneRequestRule;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class UserTelephoneController extends Controller
{
   /**
    * Get all user phone numbers
    *
    * @return Response|Application|ResponseFactory
    */
   public function getAll(): Response|Application|ResponseFactory
   {
      /** @var User $user */
      $user = auth()->user();

      $telephones = $user->{'userTelephones'};

      return api_response(100, 'Okay', $telephones);
   }

   /**
    * Add user telephone
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function add(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::createRules());
      $data = $request->all();

      try {
         $telephone = UserTelephone::addTelephone($data);

         return api_response(100, 'Ok', $telephone);
      } catch (\Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::add');

         $userTelephoneExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userTelephoneExceptions != null) {
            return $userTelephoneExceptions;
         }
      }

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

   /**
    * Edit phone number
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function edit(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::editRules());

      /** @var User $user */
      $user = auth()->user();

      try {
         /** @var UserTelephone $telephone */
         $telephone = UserTelephone::findByUserTelephone($user->{"id"}, $request->{'telephone'},);

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

         $result = $telephone->editTelephoneNumber($request->all());

         return api_response(100, "Okay", $result);
      } catch (\Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::edit');

         $userTelephoneExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userTelephoneExceptions != null) {
            return $userTelephoneExceptions;
         }
      }

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

   /**
    * Marl telephone number as primary
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function markPrimary(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::marKPrimaryRules());

      /** @var User $user */
      $user = auth()->user();

      try {
         /** @var UserTelephone $telephone */
         $telephone = UserTelephone::findByUserTelephone($user->{"id"}, $request->{'telephone'},);

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

         $results = $telephone->markTelephoneAsPrimary($request->all());

         return api_response(100, "Okay", $results);
      } catch (\Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::markPrimary');

         $userTelephoneExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userTelephoneExceptions != null) {
            return $userTelephoneExceptions;
         }
      }

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

   /**
    * Deactivate number
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function deactivate(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::deactivateRules());

      /** @var User $user */
      $user = auth()->user();

      try {
         /** @var UserTelephone $telephone */
         $telephone = UserTelephone::findByUserTelephone($user->{"id"}, $request->{'telephone'},);

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

         $results = $telephone->deactivate($request->all());

         return api_response(100, "Okay", $results);
      } catch (Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::deactivate');

         $userTelephoneExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userTelephoneExceptions != null) {
            return $userTelephoneExceptions;
         }
      }

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

   /**
    * Delete phone number
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function delete(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::deleteRules());

      /** @var User $user */
      $user = auth()->user();

      try {
         /** @var UserTelephone $telephone */
         $telephone = UserTelephone::findByUserTelephone($user->{"id"}, $request->{'telephone'},);

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

         $result = $telephone->deleteTelephone($request->all());

         return api_response(100, "Okay", $result);
      } catch (\Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::delete');

         $userTelephoneExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userTelephoneExceptions != null) {
            return $userTelephoneExceptions;
         }
      }

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

   /**
    * Verify telephone
    *
    * @param Request $request
    * @return Application|ResponseFactory|Response
    */
   public function verify(Request $request): Response|Application|ResponseFactory
   {
      $request->validate(UserTelephoneRequestRule::verifyRules());

      try {
         $Results = UserTelephone::verify(($request->all()));

         return api_response(100, "Okay", $Results);
      } catch (Exception $exception) {
         log_debug(exception: $exception, prefix: 'UserTelephoneController::verify');

         $userEmailExceptions = self::returnUserTelephoneExceptions($exception);
         if ($userEmailExceptions != null) {
            return $userEmailExceptions;
         }
      }

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

   // Controller utilities

   /**
    * Return exception
    *
    * @param Exception $exception
    * @return Response|Application|ResponseFactory|null
    */
   protected static function returnUserTelephoneExceptions(Exception $exception): Response|Application|ResponseFactory|null
   {
      if ($exception instanceof TelephoneAlreadyExistException || $exception instanceof InvalidTelephone || $exception instanceof InvalidDeletingPrimaryTelephoneAttempt || $exception instanceof InvalidPasswordException || $exception instanceof InvalidEditingPrimaryTelephoneAttempt || $exception instanceof InvalidNumberDeactivationAttempt) {
         return api_response(120, $exception->getMessage());
      }

      return null;
   }
}
