<?php

use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\path_alias\Entity\PathAlias;
use Drupal\user\Entity\Role;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;

/**
 * Implements hook_install().
 *
 * Delegates to the rebuild function so that normal module installs and
 * container rebuilds both produce the same result.
 */
function riverside_pt_install() {
  _riverside_pt_rebuild();
}

/**
 * Rebuilds the Riverside PT site structure from code.
 *
 * This function is idempotent and can be safely called multiple times.
 * It is the single source of truth for content types, fields, roles,
 * and navigation used by the Docker entrypoint.
 */
function _riverside_pt_rebuild(): void {
  $entity_type_manager = \Drupal::entityTypeManager();
  $storage_node_type = $entity_type_manager->getStorage('node_type');
  $storage_role = $entity_type_manager->getStorage('user_role');
  $storage_field_storage = $entity_type_manager->getStorage('field_storage_config');
  $storage_field_config = $entity_type_manager->getStorage('field_config');

  // --- Content types (idempotent) ---
  if (!$storage_node_type->load('appointment')) {
    NodeType::create([
      'type' => 'appointment',
      'name' => 'Appointment',
      'description' => 'A booking between a Patient and a Provider at a particular time.',
      'new_revision' => FALSE,
      'display_submitted' => FALSE,
    ])->save();
  }

  if (!$storage_node_type->load('provider_availability')) {
    NodeType::create([
      'type' => 'provider_availability',
      'name' => 'Provider Availability',
      'description' => 'A window of time during which a Provider is available for appointments.',
      'new_revision' => FALSE,
      'display_submitted' => FALSE,
    ])->save();
  }

  // --- Role (idempotent) ---
  if (!$storage_role->load('provider')) {
    Role::create(['id' => 'provider', 'label' => 'Provider'])->save();
  }

  // --- Field storages (idempotent) ---
  $field_storages = [
    'field_appointment_date' => [
      'entity_type' => 'node',
      'type'        => 'datetime',
      'settings'    => ['datetime_type' => 'datetime'],
    ],
    'field_duration_minutes' => [
      'entity_type' => 'node',
      'type'        => 'integer',
    ],
    'field_service_type' => [
      'entity_type' => 'node',
      'type'        => 'list_string',
      'settings'    => [
        'allowed_values' => [
          'diagnostic'              => 'Diagnostic',
          'sports_rehab'            => 'Sports Rehab',
          'pre_post_surgical_rehab' => 'Pre/Post-Surgical Rehab',
          'neurological_pt'         => 'Neurological PT',
        ],
      ],
    ],
    'field_provider' => [
      'entity_type' => 'node',
      'type'        => 'entity_reference',
      'settings'    => ['target_type' => 'user'],
    ],
    'field_start_datetime' => [
      'entity_type' => 'node',
      'type'        => 'datetime',
      'settings'    => ['datetime_type' => 'datetime'],
    ],
    'field_end_datetime' => [
      'entity_type' => 'node',
      'type'        => 'datetime',
      'settings'    => ['datetime_type' => 'datetime'],
    ],
  ];

  foreach ($field_storages as $field_name => $definition) {
    if (!$storage_field_storage->load("node.$field_name")) {
      FieldStorageConfig::create([
        'field_name' => $field_name,
      ] + $definition)->save();
    }
  }

  // Clear field definition cache so FieldConfig creation can see the storages.
  \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();

  // --- Field configs (idempotent) ---
  $field_configs = [
    // Appointment bundle
    'node.appointment.field_appointment_date' => [
      'field_name'  => 'field_appointment_date',
      'entity_type' => 'node',
      'bundle'      => 'appointment',
      'label'       => 'Appointment Date',
      'required'    => TRUE,
    ],
    'node.appointment.field_duration_minutes' => [
      'field_name'  => 'field_duration_minutes',
      'entity_type' => 'node',
      'bundle'      => 'appointment',
      'label'       => 'Duration (Minutes)',
      'required'    => TRUE,
    ],
    'node.appointment.field_service_type' => [
      'field_name'  => 'field_service_type',
      'entity_type' => 'node',
      'bundle'      => 'appointment',
      'label'       => 'Service Type',
      'required'    => TRUE,
    ],
    'node.appointment.field_provider' => [
      'field_name'  => 'field_provider',
      'entity_type' => 'node',
      'bundle'      => 'appointment',
      'label'       => 'Provider',
      'required'    => TRUE,
      'settings'    => [
        'handler'          => 'default:user',
        'handler_settings' => [
          'filter' => ['type' => '_role', 'role' => ['provider' => 'provider']],
        ],
      ],
    ],
    // Provider availability bundle
    'node.provider_availability.field_provider' => [
      'field_name'  => 'field_provider',
      'entity_type' => 'node',
      'bundle'      => 'provider_availability',
      'label'       => 'Provider',
      'required'    => TRUE,
      'settings'    => [
        'handler'          => 'default:user',
        'handler_settings' => [
          'filter' => ['type' => '_role', 'role' => ['provider' => 'provider']],
        ],
      ],
    ],
    'node.provider_availability.field_start_datetime' => [
      'field_name'  => 'field_start_datetime',
      'entity_type' => 'node',
      'bundle'      => 'provider_availability',
      'label'       => 'Start',
      'required'    => TRUE,
    ],
    'node.provider_availability.field_end_datetime' => [
      'field_name'  => 'field_end_datetime',
      'entity_type' => 'node',
      'bundle'      => 'provider_availability',
      'label'       => 'End',
      'required'    => TRUE,
    ],
  ];

  foreach ($field_configs as $field_id => $definition) {
    if (!$storage_field_config->load($field_id)) {
      FieldConfig::create($definition)->save();
    }
  }

  // Navigation and basic site settings (these are intentionally destructive on menu).
  try {
    _riverside_pt_build_navigation();
  }
  catch (\Exception $e) {
    \Drupal::logger('riverside_pt')->error('Navigation setup failed: @msg', ['@msg' => $e->getMessage()]);
  }

  \Drupal::configFactory()->getEditable('system.site')
    ->set('page.front', '/home')
    ->save();
}

function _riverside_pt_build_navigation(): void {
  $em = \Drupal::entityTypeManager();

  foreach ($em->getStorage('menu_link_content')->loadByProperties(['menu_name' => 'main']) as $link) {
    $link->delete();
  }

  foreach (['Services', 'About', 'FAQ', 'Contact'] as $title) {
    if ($em->getStorage('node')->loadByProperties(['title' => $title, 'type' => 'page'])) {
      continue;
    }
    $node = Node::create(['type' => 'page', 'title' => $title, 'status' => 1]);
    $node->save();
    PathAlias::create([
      'path'     => '/node/' . $node->id(),
      'alias'    => '/' . strtolower($title),
      'langcode' => 'en',
    ])->save();
  }

  $defs = [
    ['title' => 'Home',                'uri' => 'route:<front>',      'weight' => 0, 'class' => NULL],
    ['title' => 'Services',            'uri' => 'internal:/services', 'weight' => 1, 'class' => NULL],
    ['title' => 'About',               'uri' => 'internal:/about',    'weight' => 2, 'class' => NULL],
    ['title' => 'FAQ',                 'uri' => 'internal:/faq',      'weight' => 3, 'class' => NULL],

    ['title' => 'Contact',             'uri' => 'internal:/contact',  'weight' => 4, 'class' => 'nav-cta nav-cta--primary'],
    ['title' => 'Book An Appointment', 'uri' => 'internal:/schedule', 'weight' => 5, 'class' => 'nav-cta nav-cta--primary'],
  ];

  foreach ($defs as $def) {
    $options = $def['class'] ? ['attributes' => ['class' => explode(' ', $def['class'])]] : [];
    MenuLinkContent::create([
      'title'     => $def['title'],
      'link'      => ['uri' => $def['uri'], 'options' => $options],
      'menu_name' => 'main',
      'weight'    => $def['weight'],
      'enabled'   => TRUE,
    ])->save();
  }
}
