<?php

namespace ModernFields\Sync\Services;

use ModernFields\ImportExport\Services\ExportService;
use ModernFields\ImportExport\Services\ImportService;

defined('ABSPATH') || exit;

/**
 * Reads and writes taxonomy definition JSON files in the active theme directory.
 *
 * When a `mf-json/taxonomies/` folder exists in the theme, each saved taxonomy
 * definition is automatically persisted as `{key}.json` so developers can
 * version-control their definitions alongside their theme.
 *
 * @since 0.9.0
 */
class JsonSyncTaxonomyService
{
  public function __construct(
    protected ExportService $exportService,
    protected ImportService $importService,
  ) {}

  /**
   * Returns the absolute path to the theme's mf-json/taxonomies directory,
   * or null if it does not exist.
   *
   * @since 0.9.0
   */
  public function getJsonDir(): ?string
  {
    $dir = get_stylesheet_directory() . '/mf-json';
    return is_dir($dir) ? $dir : null;
  }

  /**
   * Serializes a taxonomy definition and writes it to the theme's
   * mf-json/taxonomies directory. Silently skips if the directory does not
   * exist or the definition has no key.
   *
   * @since 0.9.0
   * @param int $post_id
   * @return void
   */
  public function writeDefinitionJson(int $post_id): void
  {
    $dir = $this->getJsonDir();
    if (!$dir) {
      return;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_status === 'trash') {
      return;
    }

    $data = $this->exportService->export([], [], [$post_id]);

    if (empty($data['taxonomies'])) {
      return;
    }

    $definition = $data['taxonomies'][0];
    $key        = $definition['config']['key'] ?? null;

    if (empty($key)) {
      return;
    }

    file_put_contents(
      $dir . '/taxonomy-' . sanitize_file_name($key) . '.json',
      wp_json_encode($definition, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
    );
  }

  /**
   * Deletes the JSON file for a taxonomy definition when it is trashed.
   *
   * @since 0.9.0
   * @param int $post_id
   * @return void
   */
  public function deleteDefinitionJson(int $post_id): void
  {
    $dir = $this->getJsonDir();
    if (!$dir) {
      return;
    }

    $post   = get_post($post_id);
    $config = $post && $post->post_content ? json_decode($post->post_content, true) : [];
    $key    = $config['key'] ?? null;

    if (empty($key)) {
      return;
    }

    $file = $dir . '/taxonomy-' . sanitize_file_name($key) . '.json';
    if (file_exists($file)) {
      unlink($file);
    }
  }

  /**
   * Returns the sync status for every JSON file found in the theme's
   * mf-json directory (taxonomy-*.json files only).
   *
   * Each entry contains:
   * - key          string        Taxonomy key (matches config.key)
   * - item_id      int|null      WP post ID if the definition exists on this site
   * - json_modified string|null  ISO-8601 modified date stored in the JSON file
   * - has_update   bool          true when the JSON file is newer than the DB record
   *
   * @since 0.9.0
   * @return array
   */
  public function getAllSyncStatuses(): array
  {
    $dir = $this->getJsonDir();
    if (!$dir) {
      return [];
    }

    $files    = glob($dir . '/taxonomy-*.json') ?: [];
    $statuses = [];

    foreach ($files as $file) {
      $raw = file_get_contents($file);
      if (!$raw) {
        continue;
      }

      $data = json_decode($raw, true);
      if (empty($data['uuid'])) {
        continue;
      }

      $uuid          = $data['uuid'];
      $item_id       = $this->findDefinitionByUuid($uuid);
      $json_modified = $data['modified'] ?? null;
      $has_update    = false;

      if ($item_id && $json_modified) {
        $item_modified = get_post_modified_time('U', true, $item_id);
        $has_update    = strtotime($json_modified) > (int) $item_modified;
      }

      $statuses[] = [
        'key'           => $data['config']['key'] ?? pathinfo($file, PATHINFO_FILENAME),
        'item_id'       => $item_id,
        'json_modified' => $json_modified,
        'has_update'    => $has_update,
      ];
    }

    return $statuses;
  }

  /**
   * Imports a taxonomy definition from its JSON file in the theme directory.
   *
   * @since 0.9.0
   * @param string $key Taxonomy key (filename without extension).
   * @return array Import report from ImportService.
   */
  public function importFromJson(string $key): array
  {
    $dir = $this->getJsonDir();
    if (!$dir) {
      return ['error' => 'no_theme_json_dir'];
    }

    $file = $dir . '/taxonomy-' . sanitize_file_name($key) . '.json';
    if (!file_exists($file)) {
      return ['error' => 'file_not_found'];
    }

    $definition_data = json_decode(file_get_contents($file), true);
    if (empty($definition_data['uuid'])) {
      return ['error' => 'invalid_json'];
    }

    $payload = [
      'mf_version'  => MODERN_FIELDS_VERSION,
      'exported_at' => $definition_data['modified'] ?? null,
      'groups'      => [],
      'post_types'  => [],
      'taxonomies'  => [$definition_data],
    ];

    return $this->importService->import($payload, [$definition_data['uuid']]);
  }

  /**
   * @since 0.9.0
   */
  protected function findDefinitionByUuid(string $uuid): ?int
  {
    $posts = get_posts([
      'post_type'      => MODERN_FIELDS_TAXONOMIES_CPT_SLUG,
      'post_status'    => 'any',
      'posts_per_page' => 1,
      'meta_key'       => 'mf_uuid',
      'meta_value'     => $uuid,
      'fields'         => 'ids',
    ]);

    return !empty($posts) ? (int) $posts[0] : null;
  }
}
