<?php
/**
 * BookiFlex Core
 *
 * @package    BookiFlex
 * @subpackage Core
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Core\Admin\CPT;

use BookiFlex\Core\Admin\CPT\Event\AccommodationTypeWasCreated;
use BookiFlex\Core\Admin\CPT\Event\AccommodationTypeWasDeleted;
use BookiFlex\Core\Admin\CPT\Event\AccommodationTypeWasUpdated;
use BookiFlex\Core\Admin\CPT\Trait\DispatchesCPTEvents;
use BookiFlex\Core\Contract\PluginInterface;
use BookiFlex\Core\Contract\RoleCapabilitiesInterface;

defined( 'ABSPATH' ) || exit;

abstract class AccommodationType extends AbstractCPT
{
    use DispatchesCPTEvents;
    public const POST_TYPE                     = 'bflex-rental-unit';
    public const FIELD_SHORT_CODE                    = 'bflex__at__short_code';
    public const FIELD_LIVING_SPACE            = 'bflex__at__living_space';
    public const FIELD_ACCOMMODATION_CATEGORY      = 'bflex__at__accommodation_category';
    public const FIELD_ACCOMMODATION_AVAILABLE_UNITS       = 'bflex__at__accommodation_available_units';
    public const FIELD_KEY_AMENITIES               = 'bflex__at__amenities';
    public const FIELD_MAIN_SLEEPING_CAPACITY         = 'bflex__at__main_sleeping_capacity';
    public const FIELD_MAIN_SLEEPING_ALLOWED_OCCUPANCY  = 'bflex__at__main_sleeping_allowed_occupancy';
    public const FIELD_ADDITIONAL_SLEEPING_PLACES        = 'bflex__at__additional_sleeping_places';
    public const FIELD_ENABLE_EXTRA_OCCUPANCY = 'bflex__at__enable_extra_occupancy';
    public const FIELD_CHILD_ALLOWED_ON_MAIN_PLACE  = 'bflex__at__child_allowed_on_main_place';
    public const FIELD_CHILD_ALLOWED_ON_EXTRA_PLACE = 'bflex__at__child_allowed_on_extra_place';
    public const FIELD_CHILD_ALLOWED_WITHOUT_PLACE  = 'bflex__at__child_allowed_without_place';
    public const FIELD_ACCOMMODATION_GALLERY   = 'bflex__at__accommodation_gallery';
    public const FIELD_THUMBNAIL               = 'thumbnail_id';
    public const FIELD_ADDRESS   = 'bflex__at__contact__address';
    public const FIELD_PHONE     = 'bflex__at__contact__phone';
    public const FIELD_EMAIL     = 'bflex__at__contact__email';
    public const FIELD_LONGITUDE = 'bflex__at__location__longitude';
    public const FIELD_LATITUDE  = 'bflex__at__location__latitude';
    public const FIELD_ROOMS_COUNT = 'bflex__at__rooms_count';
    public const FIELD_CHECKIN_INSTRUCTIONS = 'bflex__at__checkin_instructions';

    public function register(PluginInterface $plugin): void
    {
        parent::register($plugin);
        $this->plugin->addAction('pre_get_posts', [$this, 'enableMenuOrderSorting']);
        $this->registerShortCodeAutoGeneration(self::FIELD_SHORT_CODE);

        // Register event hooks from trait
        $this->registerEventHooks();

        // Thumbnail column in list table
        $this->plugin->addFilter('manage_' . self::POST_TYPE . '_posts_columns', [$this, 'addThumbnailColumn']);
        $this->plugin->addAction('manage_' . self::POST_TYPE . '_posts_custom_column', [$this, 'renderThumbnailColumn'], 10, 2);
    }

    /**
     * Insert "Image" column before "title"
     */
    public function addThumbnailColumn(array $columns): array
    {
        $result = [];

        foreach ($columns as $key => $label) {
            if ($key === 'title') {
                $result['bflex_thumbnail'] = __('Image', 'bookiflex');
            }
            $result[$key] = $label;
        }

        return $result;
    }

    /**
     * Render thumbnail or placeholder in list column
     */
    public function renderThumbnailColumn(string $column, int $postId): void
    {
        if ($column !== 'bflex_thumbnail') {
            return;
        }

        if (has_post_thumbnail($postId)) {
            echo get_the_post_thumbnail($postId, [80, 80]);
        } else {
            echo '<span class="bflex-thumbnail-placeholder dashicons dashicons-format-image"></span>';
        }
    }

    public function registerPostType(): void
    {
        $labels = [
            'name'                  => _x('Rental Units', 'Post type general name', 'bookiflex'),
            'singular_name'         => _x('Rental Unit', 'Post type singular name', 'bookiflex'),
            'menu_name'             => _x('Rental Units', 'Admin Menu text', 'bookiflex'),
            'name_admin_bar'        => _x('Rental Unit', 'Add New on Toolbar', 'bookiflex'),
            'add_new'               => __('Add New', 'bookiflex'),
            'add_new_item'          => __('Add New', 'bookiflex'),
            'new_item'              => __('New Rental Unit', 'bookiflex'),
            'edit_item'             => __('Edit Rental Unit', 'bookiflex'),
            'view_item'             => __('View Rental Unit', 'bookiflex'),
            'all_items'             => __('Rental Units', 'bookiflex'),
            'search_items'          => __('Search', 'bookiflex'),
            'not_found'             => __('Nothing found.', 'bookiflex'),
            'not_found_in_trash'    => __('Nothing found in Trash.', 'bookiflex'),
            'featured_image'        => _x('Cover Image', 'Overrides the "Featured Image" phrase for this post type. Added in 4.3', 'bookiflex'),
            'set_featured_image'    => _x('Set cover image', 'Overrides the "Set featured image" phrase for this post type. Added in 4.3', 'bookiflex'),
            'remove_featured_image' => _x('Remove cover image', 'Overrides the "Remove featured image" phrase for this post type. Added in 4.3', 'bookiflex'),
            'use_featured_image'    => _x('Use as cover image', 'Overrides the "Use as featured image" phrase for this post type. Added in 4.3', 'bookiflex'),
            'attributes'            => __('Attributes', 'bookiflex'),
        ];

        $args = [
            'labels'             => $labels,
            'public'             => true,
            'publicly_queryable' => false,
            'show_ui'            => true,
            'show_in_menu'       => 'bookiflex',
            'query_var'          => true,
            'rewrite'            => ['slug' => self::POST_TYPE],
            'has_archive'        => false,
            'hierarchical'       => false,
            'menu_position'      => 0,
            'supports'           => ['title', 'thumbnail'],
            'capability_type'    => self::POST_TYPE,
            'capabilities'       => [
                'edit_post'              => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'read_post'              => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'delete_post'            => RoleCapabilitiesInterface::DELETE_CONFIGURATION,
                'edit_posts'             => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'edit_others_posts'      => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'publish_posts'          => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'read_private_posts'     => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'delete_posts'           => RoleCapabilitiesInterface::DELETE_CONFIGURATION,
                'delete_private_posts'   => RoleCapabilitiesInterface::DELETE_CONFIGURATION,
                'delete_published_posts' => RoleCapabilitiesInterface::DELETE_CONFIGURATION,
                'delete_others_posts'    => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'edit_private_posts'     => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
                'edit_published_posts'   => RoleCapabilitiesInterface::MANAGE_CONFIGURATION,
            ],
            'map_meta_cap' => false,
        ];

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

    // ===================================================================
    // Event-related methods (DispatchesCPTEvents trait implementation)
    // ===================================================================

    /**
     * Gather all relevant data from AccommodationType post
     *
     * This data is included in events and used for change detection
     */
    protected function gatherPostData(int $postId): array
    {
        $post = get_post($postId);

        return [
            'name' => $post->post_title ?? '',
            'status' => $post->post_status ?? '',
            'available_units' => (int)carbon_get_post_meta(
                $postId,
                self::FIELD_ACCOMMODATION_AVAILABLE_UNITS
            ),
            'short_code' => carbon_get_post_meta($postId, self::FIELD_SHORT_CODE) ?: '',
            'accommodation_category' => carbon_get_post_meta(
                $postId,
                self::FIELD_ACCOMMODATION_CATEGORY
            ) ?: '',
        ];
    }

    /**
     * Create AccommodationTypeWasCreated event
     */
    protected function createCreatedEvent(int $postId, array $data): object
    {
        return new AccommodationTypeWasCreated($postId, $data);
    }

    /**
     * Create AccommodationTypeWasUpdated event
     */
    protected function createUpdatedEvent(int $postId, array $data, array $changes): object
    {
        return new AccommodationTypeWasUpdated($postId, $data, $changes);
    }

    /**
     * Create AccommodationTypeWasDeleted event
     */
    protected function createDeletedEvent(int $postId, array $data): object
    {
        return new AccommodationTypeWasDeleted($postId, $data);
    }

    /**
     * Custom change detection for AccommodationType
     *
     * Detects changes in critical fields like available_units, status, and name
     */
    protected function detectChanges(array $previous, array $current): array
    {
        $changes = [];

        // Critical field: available_units (impacts Quota)
        if (isset($previous['available_units'], $current['available_units'])
            && $previous['available_units'] !== $current['available_units']
        ) {
            $changes['available_units'] = [
                'old' => $previous['available_units'],
                'new' => $current['available_units']
            ];
        }

        // Status change (publish/draft/etc)
        if (isset($previous['status'], $current['status'])
            && $previous['status'] !== $current['status']
        ) {
            $changes['status'] = [
                'old' => $previous['status'],
                'new' => $current['status']
            ];
        }

        // Name change
        if (isset($previous['name'], $current['name'])
            && $previous['name'] !== $current['name']
        ) {
            $changes['name'] = [
                'old' => $previous['name'],
                'new' => $current['name']
            ];
        }

        // Short code change
        if (isset($previous['short_code'], $current['short_code'])
            && $previous['short_code'] !== $current['short_code']
        ) {
            $changes['short_code'] = [
                'old' => $previous['short_code'],
                'new' => $current['short_code']
            ];
        }

        // Category change
        if (isset($previous['accommodation_category'], $current['accommodation_category'])
            && $previous['accommodation_category'] !== $current['accommodation_category']
        ) {
            $changes['accommodation_category'] = [
                'old' => $previous['accommodation_category'],
                'new' => $current['accommodation_category']
            ];
        }

        return $changes;
    }
}
