<?php

declare(strict_types=1);

namespace Drupal\lms_xapi_lesson\Form;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\lms\Controller\CourseControllerTrait;
use Drupal\lms\Entity\LessonStatusInterface;
use Drupal\lms\Form\AnswerFormTrait;
use Drupal\lms\TrainingManager;
use Drupal\lms_xapi\XapiService;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form for Articulate 360 lessons.
 */
final class XapiLessonForm extends FormBase {

  use CourseControllerTrait;
  use AnswerFormTrait;

  /**
   * Constructor.
   */
  public function __construct(
    private readonly TrainingManager $trainingManager,
    private readonly AccountInterface $currentUser,
    private readonly XapiService $xapi,
  ) {}

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new static(
      $container->get('lms.training_manager'),
      $container->get(AccountInterface::class),
      $container->get(XapiService::class)
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'xapi_lesson_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, ?LessonStatusInterface $lesson_status = NULL) {
    \assert($lesson_status !== NULL);
    $form['actions'] = [
      '#type' => 'actions',
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Finish lesson'),
      ],
    ];
    return $form;
  }

  /**
   * As in the method name.
   */
  private function getLessonStatus(FormStateInterface $form_state): LessonStatusInterface {
    return $form_state->getBuildInfo()['args'][0];
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $lesson_status = $this->getLessonStatus($form_state);

    // Update lesson score from LRS.
    $lesson = $lesson_status->getLesson();
    $lms_id = $this->xapi->getLmsId($lesson, $this->currentUser, new CacheableMetadata());
    $lrs_score = $this->xapi->getScoreFromLrs($lms_id);
    if ($lrs_score !== NULL) {
      $lesson_score = \round($lrs_score * 100);
      $lesson_status->setScore((int) $lesson_score);
    }
    $this->trainingManager->updateLessonStatus($lesson_status);

    $course_status = $lesson_status->getCourseStatus();

    try {
      $next_lesson_status = $this->trainingManager->getNextLessonStatus($course_status);
    }
    catch (\Exception $e) {
      $this->trainingManager->updateCourseStatus($course_status);
      $url = $this->handleError($course_status->getCourse(), $e);
      $form_state->setRedirectUrl($url);
      return;
    }

    if ($next_lesson_status === NULL) {
      $this->trainingManager->updateCourseStatus($course_status, TRUE);
      $url = $this->handleFinishedCourse($course_status);
      $form_state->setRedirectUrl($url);
      return;
    }

    $next_lesson_status->setCurrentActivityDelta(0);
    $next_lesson_status->save();
    $course_status->set('current_lesson_status', $next_lesson_status);
    $this->trainingManager->updateCourseStatus($course_status, TRUE);

    $form_state->setRedirect('lms.group.answer_form', [
      'group' => $course_status->get('gid')->target_id,
      'lesson_delta' => $next_lesson_status->getCurrentLessonDelta(),
      'activity_delta' => $next_lesson_status->getCurrentActivityDelta(),
    ]);
  }

}
