<?php

namespace Yalogica\NinjaDraw\System;

defined('ABSPATH') || exit;

use Yalogica\NinjaDraw\Models\DataModel;
use Yalogica\NinjaDraw\Models\AccessModel;
use Yalogica\NinjaDraw\Models\SettingsModel;
use Yalogica\NinjaDraw\Models\FreemiusModel;

class Admin
{
  private const NOTICE_META_KEY = '_ninjadraw_admin_notice_hide_until';
  private const NOTICE_NONCE_ACTION = 'ninjadraw_dismiss_admin_notice';

  public function __construct()
  {
    add_action('init', [$this, 'init']);
  }

  public function init()
  {
    $this->registerPostType();

    if (!is_admin()) {
      return;
    }

    if (AccessModel::currentUserCan(AccessModel::ACCESS_RIGHT_VIEW)) {
      add_action('admin_menu', [$this, 'adminMenu']);
      add_filter('submenu_file', [$this, 'highlightAdminMenu'], 10, 2);
      add_action('wp_loaded', [$this, 'redirect']);
      add_action('script_loader_tag', [$this, 'scriptLoaderTag'], 10, 3);
      add_action('admin_init', [$this, 'initAdminHeaders']);
      add_action('admin_enqueue_scripts', [$this, 'enqueueAdminAssets']);

      if (!FreemiusModel::isLicensed()) {
        add_action('admin_notices', [$this, 'adminNotices']);
        add_action('admin_enqueue_scripts', [$this, 'adminNoticesScripts']);
        add_action('wp_ajax_ninjadraw_dismiss_admin_notice', [$this, 'adminNoticesAjaxDismiss']);
      }
    } else if (current_user_can('administrator')) {
      add_action('admin_menu', [$this, 'adminMenu']);
    }
  }

  public function registerPostType()
  {
    $labels = [
      'name' => esc_html__('NinjaDraw Diagrams', 'ninjadraw'),
      'singular_name' => esc_html__('NinjaDraw Diagram', 'ninjadraw'),
    ];
    $args = [
      'labels' => $labels,
      'public' => false,  // removes the permalink option
      'publicly_queryable' => false, // remove preview page
      'exclude_from_search' => true,
      'show_ui' => false,
      'show_in_menu' => false,
      'show_in_rest' => false,
      'rewrite' => false,
      'query_var' => false,
      'capability_type' => 'post',
      'has_archive' => false,
      'hierarchical' => false,
      'supports' => ['title']
    ];

    register_post_type(DataModel::POST_TYPE, $args);
  }

  public function adminMenu()
  {
    if (AccessModel::currentUserCan(AccessModel::ACCESS_RIGHT_VIEW)) {
      // add "edit_posts" if we want to give access to author, editor and contributor roles
      add_menu_page(esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('NinjaDraw', 'ninjadraw'), 'read', 'ninjadraw', [$this, 'showPage'], 'data:image/svg+xml;base64,' . base64_encode(SettingsModel::ICON));
      add_submenu_page('ninjadraw', esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('All Diagrams', 'ninjadraw'), 'read', 'ninjadraw', [$this, 'showPage']);
      add_submenu_page('ninjadraw', esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('Add New', 'ninjadraw'), 'read', 'ninjadraw&action=new', [$this, 'showPage']);
      add_submenu_page('ninjadraw', esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('Guide', 'ninjadraw'), 'read', 'ninjadraw-guide', [$this, 'showPageGuide']);
      add_submenu_page('ninjadraw', esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('Settings', 'ninjadraw'), 'manage_options', 'ninjadraw-settings', [$this, 'showPageSettings']);
    } else {
      add_menu_page(esc_html__('NinjaDraw', 'ninjadraw'), esc_html__('NinjaDraw', 'ninjadraw'), 'manage_options', 'ninjadraw-settings', [$this, 'showPageSettings'], 'data:image/svg+xml;base64,' . base64_encode(SettingsModel::ICON));
    }
  }

  public function highlightAdminMenu($submenu_file, $parent_file)
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (in_array($page, ['ninjadraw'])) {
      $action = sanitize_key(filter_input(INPUT_GET, 'action', FILTER_DEFAULT));
      if (in_array($action, ['new'])) {
        $submenu_file = "ninjadraw&action={$action}";
      }
    }
    return $submenu_file;
  }

  public function redirect()
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (!in_array($page, ['ninjadraw'], true)) {
      return;
    }

    $action = sanitize_key(filter_input(INPUT_GET, 'action', FILTER_DEFAULT));
    if (!$action) {
      return;
    }

    $id = absint(filter_input(INPUT_GET, 'id', FILTER_DEFAULT));
    $request_uri = wp_unslash($_SERVER['REQUEST_URI'] ?? '');
    $request_uri = ! empty($request_uri) ? esc_url_raw($request_uri) : '';

    if (!in_array($action, ['new', 'copy', 'edit', 'trash', 'restore', 'delete'], true) && !empty($request_uri)) {
      $url = remove_query_arg(['action', 'id', '_wpnonce'], $request_uri);
      wp_safe_redirect($url, 303);
      exit;
    }
  
    if (!in_array($action, ['new', 'copy'], true)) {
      if (!AccessModel::currentUserCan(AccessModel::ACCESS_RIGHT_CREATE)) {
        wp_die(esc_html__('Sorry, you are not allowed to access this page.', 'ninjadraw'), 403);
      }
    } elseif (!in_array($action, ['edit'], true)) {
      if (!DataModel::currentUserCan($id, AccessModel::ACCESS_RIGHT_EDIT)) {
        wp_die(esc_html__('Sorry, you are not allowed to access this page.', 'ninjadraw'), 403);
      }
    } elseif (!in_array($action, ['trash', 'restore', 'delete'], true)) {
      if (!DataModel::currentUserCan($id, AccessModel::ACCESS_RIGHT_DELETE)) {
        wp_die(esc_html__('Sorry, you are not allowed to access this page.', 'ninjadraw'), 403);
      }
    }
  }

  public function scriptLoaderTag($tag, $handle, $src)
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (!in_array($page, ['ninjadraw', 'ninjadraw-settings'], true)) {
      return $tag;
    }

    if ($handle == 'ninjadraw-editor') {
      $excalidraw_asset_path = wp_parse_url(NINJADRAW_PLUGIN_URL . 'assets/vendor/excalidraw/', PHP_URL_PATH);

      $script = [];
      $script[] = '<script>';
      $script[] = 'window.EXCALIDRAW_EXPORT_SOURCE = "https://excalidraw.com";';
      $script[] = 'window.EXCALIDRAW_ASSET_PATH = "' . $excalidraw_asset_path . '";';
      $script[] = '</script>';
      
      // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
      $script[] = sprintf('<script type="module" src="%s" defer></script>', esc_url($src));

      return join("\n", $script);
    } else if ($handle == "ninjadraw-settings") {
      $script = [];

      // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
      $script[] = sprintf('<script type="module" src="%s" defer></script>', esc_url($src));

      return join("\n", $script);
    }

    return $tag;
  }

  public function initAdminHeaders()
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));

    if ($page === 'ninjadraw') {
      header('Permissions-Policy: unload=(self)');
    }
  }

  public function enqueueAdminAssets($hook) {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (!in_array($page, ['ninjadraw', 'ninjadraw-guide', 'ninjadraw-settings'], true)) {
      return;
    }
    
    wp_enqueue_style('ninjadraw', NINJADRAW_PLUGIN_URL . 'assets/css/style.css', [], NINJADRAW_PLUGIN_VERSION, 'all');

    $action = sanitize_key(filter_input(INPUT_GET, 'action', FILTER_DEFAULT));
    if (in_array($action, ['edit', 'new'], true)) {  
      wp_enqueue_style('ninjadraw-excalidraw', NINJADRAW_PLUGIN_URL . 'assets/vendor/excalidraw/index.css', [], NINJADRAW_PLUGIN_VERSION, 'all');
    }
  }

  public function adminNotices()
  {
    $page = sanitize_key($_GET['page'] ?? '');
    if (!in_array($page, ['ninjadraw', 'ninjadraw-guide', 'ninjadraw-settings'], true)) {
      return;
    }

    $user_id    = get_current_user_id();
    $hide_until = (int) get_user_meta($user_id, self::NOTICE_META_KEY, true);
    if ($hide_until > time()) {
      return;
    }

    $trial_url = esc_url(admin_url('admin.php?page=ninjadraw-pricing&trial=true'));
    $free_vs_pro_url = esc_url('https://yalogica.com/ninjadraw/');

    echo '<div class="notice notice-info is-dismissible ninjadraw-admin-notice" style="background-image: linear-gradient(to bottom, rgb(87 162 255 / 30%) 0%, #fff 70%);">';

    echo '<h3>';
    echo esc_html__('Thank you for using NinjaDraw!', 'ninjadraw');
    echo '</h3>';

    echo '<p>' . wp_kses(__( 'You are using the <b>Lite</b> plan with the following limitations:', 'ninjadraw' ), ['b' => []] ) . '</p>';
    echo '<ul style="margin: 0 0 0.75em 1.25em; list-style: none;">';
    echo '<li>🔒 ' . esc_html__('You can create and edit up to 5 diagrams.', 'ninjadraw') . '</li>';
    echo '<li>🔒 ' . esc_html__('Global plugin settings are disabled.', 'ninjadraw') . '</li>';
    echo '<li>🔒 ' . esc_html__('Advanced user permissions are disabled.', 'ninjadraw') . '</li>';
    echo '</ul>';

    echo '<p style="margin-top:25px">';
    echo '<a class="button button-primary" href="' . esc_url($trial_url) . '">' . esc_html__('Unlock All Features (Free 7-Day Trial)', 'ninjadraw') . '</a> ';
    echo '<a class="button button-secondary" href="' . esc_url($free_vs_pro_url) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('Learn More', 'ninjadraw') . '</a>';
    echo '</p>';

    echo '</div>';
  }

  public function adminNoticesScripts($hook_suffix)
  {
    $page = sanitize_key($_GET['page'] ?? '');
    if (!in_array($page, ['ninjadraw', 'ninjadraw-guide', 'ninjadraw-settings'], true)) {
      return;
    }

    wp_enqueue_script('ninjadraw-admin-notice', NINJADRAW_PLUGIN_URL . 'assets/js/admin-notice.js', ['jquery'], NINJADRAW_PLUGIN_VERSION, true);
    wp_localize_script('ninjadraw-admin-notice', 'ninjadraw_globals_admin_notice', [
      'ajaxurl' => admin_url('admin-ajax.php'),
      'nonce' => wp_create_nonce(self::NOTICE_NONCE_ACTION),
    ]);
  }

  public function adminNoticesAjaxDismiss()
  {
    if (!current_user_can('edit_posts')) {
      wp_send_json_error(['message' => 'forbidden'], 403);
    }

    check_ajax_referer(self::NOTICE_NONCE_ACTION, 'nonce');

    update_user_meta(
      get_current_user_id(),
      self::NOTICE_META_KEY,
      time() + 30 * DAY_IN_SECONDS
    );

    wp_send_json_success();
  }

  public function showPage()
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (in_array($page, ['ninjadraw'])) {
      $action = sanitize_key(filter_input(INPUT_GET, 'action', FILTER_DEFAULT));

      switch ($action) {
        case 'edit':
        case 'new': {
            $id = sanitize_key(filter_input(INPUT_GET, 'id', FILTER_DEFAULT));

            if ($action == 'edit') {
              $post = get_post($id);
              if (!$post || $post->post_type !== DataModel::POST_TYPE) {
                echo '<div class="notice notice-error is-dismissible">';
                echo '<p>NinjaDraw: ' . esc_html__("The item doesn't exist or is in the wrong format.", 'ninjadraw') . '</p>';
                echo '</div>';
                return;
              }
            }

            wp_enqueue_style('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/css/notify.css', [], NINJADRAW_PLUGIN_VERSION, 'all');
            wp_enqueue_script('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/js/notify.js', [], NINJADRAW_PLUGIN_VERSION, false);

            wp_enqueue_script('ninjadraw-editor', NINJADRAW_PLUGIN_URL . 'assets/components/editor/index.js', [], NINJADRAW_PLUGIN_VERSION, false);

            wp_localize_script('ninjadraw-editor', 'ninjadraw_globals', $this->getGlobalsForEditor($id));

            wp_enqueue_media();

            require_once(NINJADRAW_PLUGIN_PATH . '/includes/Views/item.php');
          }
          break;
        default: {
            wp_enqueue_style('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/css/notify.css', [], NINJADRAW_PLUGIN_VERSION, 'all');
            wp_enqueue_script('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/js/notify.js', [], NINJADRAW_PLUGIN_VERSION, false);

            wp_enqueue_script('ninjadraw-items', NINJADRAW_PLUGIN_URL . 'assets/js/items.js', [], NINJADRAW_PLUGIN_VERSION, false);
            wp_localize_script('ninjadraw-items', 'ninjadraw_globals', $this->getGlobalsForItems());

            $table = new ListTable();
            $table->prepare_items();

            require_once(NINJADRAW_PLUGIN_PATH . '/includes/Views/items.php');
          }
      }
    }
  }

  public function showPageGuide()
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (in_array($page, ['ninjadraw-guide'])) {
      wp_enqueue_script('ninjadraw-feather-icons', NINJADRAW_PLUGIN_URL . 'assets/vendor/feather-icons/feather.js', [], NINJADRAW_PLUGIN_VERSION, false);

      wp_enqueue_style('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/css/notify.css', [], NINJADRAW_PLUGIN_VERSION, 'all');
      wp_enqueue_script('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/js/notify.js', [], NINJADRAW_PLUGIN_VERSION, false);
      
      require_once(NINJADRAW_PLUGIN_PATH . '/includes/Views/guide.php');
    }
  }

  public function showPageSettings()
  {
    $page = sanitize_key(filter_input(INPUT_GET, 'page', FILTER_DEFAULT));
    if (in_array($page, ['ninjadraw-settings'])) {
      wp_enqueue_script('ninjadraw-feather-icons', NINJADRAW_PLUGIN_URL . 'assets/vendor/feather-icons/feather.js', [], NINJADRAW_PLUGIN_VERSION, false);

      wp_enqueue_style('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/css/notify.css', [], NINJADRAW_PLUGIN_VERSION, 'all');
      wp_enqueue_script('ninjadraw-notify', NINJADRAW_PLUGIN_URL . 'assets/js/notify.js', [], NINJADRAW_PLUGIN_VERSION, false);

      wp_enqueue_script('ninjadraw-settings', NINJADRAW_PLUGIN_URL . 'assets/components/settings/index.js', [], NINJADRAW_PLUGIN_VERSION, false);
      wp_localize_script('ninjadraw-settings', 'ninjadraw_globals', $this->getGlobalsForSettings());

      require_once(NINJADRAW_PLUGIN_PATH . '/includes/Views/settings.php');
    }
  }

  private function getGlobalsForEditor($id = null)
  {
    $data = [
      'is_licensed' => FreemiusModel::isLicensed(),
      'url' => [
        'libraryreturn' => urlencode(add_query_arg(['page' => 'ninjadraw', 'action' => 'new'], admin_url('admin.php'))),
        'back' => sanitize_url(add_query_arg(['page' => 'ninjadraw'], admin_url('admin.php')))
      ],
      'item' => ['id' => $id],
      'rights' => ['publish' => AccessModel::currentUserCan(AccessModel::ACCESS_RIGHT_PUBLISH)]
    ];

    if ($id) {
      $item = DataModel::getItem($id);
      if ($item) {
        $data['url']['libraryreturn'] = urlencode(add_query_arg(['page' => 'ninjadraw', 'action' => 'edit', 'id' => $data['item']['id']], admin_url('admin.php')));
        $data['item']['title'] = $item['title'];
        $data['item']['status'] = $item['status'];
        $data['item']['source'] = $item['source'];
        $data['item']['files'] = $item['files'];
      }
    }

    return [
      'data' => $data,
      'i18n' => I18n::getTranslation(),
      'api' => [
        'nonce' => wp_create_nonce('wp_rest'),
        'url' => esc_url_raw(rest_url(NINJADRAW_PLUGIN_REST_URL))
      ]
    ];
  }

  private function getGlobalsForSettings()
  {
    $data = [
      'is_licensed' => FreemiusModel::isLicensed(),
      'url' => [
        'back' => esc_url_raw(add_query_arg(['page' => 'ninjadraw'], admin_url('admin.php'))),
        'upgrade' => FreemiusModel::getUpgradeUrl(),
        'account' => FreemiusModel::getAccountUrl(),
        'docs' => NINJADRAW_DOCS_URL
      ]
    ];

    return [
      'data' => $data,
      'i18n' => I18n::getTranslation(),
      'api' => [
        'nonce' => wp_create_nonce('wp_rest'),
        'url' => esc_url_raw(rest_url(NINJADRAW_PLUGIN_REST_URL))
      ]
    ];
  }

  private function getGlobalsForItems()
  {
    $data = [
      'is_licensed' => FreemiusModel::isLicensed()
    ];

    return [
      'data' => $data,
      'i18n' => I18n::getTranslation(),
      'api' => [
        'nonce' => wp_create_nonce('wp_rest'),
        'url' => esc_url_raw(rest_url(NINJADRAW_PLUGIN_REST_URL))
      ]
    ];
  }
}
