<?php

namespace Drupal\localgov_elections\Plugin\views\field;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Field handler to flag the node type.
 *
 * @ViewsField("election_turnout")
 */
class ElectionTurnout extends FieldPluginBase {

  /**
   * Constructs a new plugin instance.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, protected EntityTypeManagerInterface $entityTypeManager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
    );
  }

  /**
   * Leave empty to avoid a query on this field.
   */
  public function query():void {

  }

  /**
   * Render function for the election_turnout field.
   *
   * Displays the difference between number of votes of first and second
   * results in an electoral area.
   *
   * @{inheritdoc}
   */
  public function render(ResultRow $values): string {
    $node = $values->_entity;
    $election = $node->id();

    // Find all 'Election Area' nodes referencing this election.
    $query = $this->entityTypeManager->getStorage('node')->getQuery()
      ->condition('type', 'localgov_area_vote')
      ->condition('localgov_election', $election);
    // OR ->condition('localgov_election', $node);
    // OR ->condition('localgov_election.entity:node.entity_id', $election);
    // Exclude contested.
    $query->accessCheck(FALSE);
    $areas = $query->execute();

    $turnout = 0;
    $electorate = 0;

    // Add all candidate votes + spoils for each area.
    foreach ($areas as $area_id) {
      $area = $this->entityTypeManager->getStorage('node')->load($area_id);

      if ($area->get("localgov_election_no_contest")?->value == "1") {
        continue;
      }

      // Find spoils and add to turnout.
      $spoils = $area->get('localgov_election_spoils')->value;
      $turnout += $spoils;

      // Iterate through each candidate and add votes to turnout.
      $candidates = $area->get('localgov_election_candidates');

      /** @var \Drupal\paragraphs\Entity\Paragraph $candidate */
      foreach ($candidates->referencedEntities() as $candidate) {
        $votes = $candidate->get('localgov_election_votes')->value;
        $turnout += $votes;
      }

      // Find electorate and add to running total.
      $eligible_electorate = $area->get('localgov_election_electorate')->value;
      if ($area->localgov_election_votes_final?->value == 1) {
        $electorate += $eligible_electorate;
      }
    }

    // Needed to avoid division by 0.
    if ($electorate == 0) {
      return "0%";
    }

    $percentage = round(($turnout / $electorate * 100), 1);

    return '(' . $percentage . '%) ' . $turnout;
  }

}
