<?php
/**
 * Abstract Migration for Easy Invoice
 *
 * @package     EasyInvoice
 * @subpackage  Migration
 * @since       2.0.0
 */

namespace EasyInvoice\Migration\Src;

/**
 * Abstract migration class.
 *
 * Provides common functionality for all migration classes.
 *
 * @since 2.0.0
 */
abstract class AbstractMigration implements MigrationInterface {

    /**
     * Migration version.
     *
     * @since 2.0.0
     * @var string
     */
    protected $version = '2.0.0';

    /**
     * Migration description.
     *
     * @since 2.0.0
     * @var string
     */
    protected $description = '';

    /**
     * Migration log.
     *
     * @since 2.0.0
     * @var array
     */
    protected $log = [];

    /**
     * Get migration version.
     *
     * @since 2.0.0
     * @return string
     */
    public function get_version(): string {
        return $this->version;
    }

    /**
     * Get migration description.
     *
     * @since 2.0.0
     * @return string
     */
    public function get_description(): string {
        return $this->description;
    }

    /**
     * Log a message.
     *
     * @since 2.0.0
     * @param string $message Message to log.
     * @param string $level Log level (info, warning, error).
     * @return void
     */
    protected function log( string $message, string $level = 'info' ): void {
        $this->log[] = [
            'message' => $message,
            'level' => $level,
            'timestamp' => current_time( 'mysql' ),
        ];
    }

    /**
     * Get migration log.
     *
     * @since 2.0.0
     * @return array
     */
    public function get_log(): array {
        return $this->log;
    }

    /**
     * Create success result.
     *
     * @since 2.0.0
     * @param string $message Success message.
     * @return array
     */
    protected function success_result( string $message ): array {
        return [
            'success' => true,
            'message' => $message,
            'log' => $this->log,
        ];
    }

    /**
     * Create error result.
     *
     * @since 2.0.0
     * @param string $message Error message.
     * @return array
     */
    protected function error_result( string $message ): array {
        return [
            'success' => false,
            'message' => $message,
            'log' => $this->log,
        ];
    }

    /**
     * Check if option exists.
     *
     * @since 2.0.0
     * @param string $option_name Option name.
     * @return bool
     */
    protected function option_exists( string $option_name ): bool {
        return get_option( $option_name ) !== false;
    }

    /**
     * Check if post type exists.
     *
     * @since 2.0.0
     * @param string $post_type Post type name.
     * @return bool
     */
    protected function post_type_exists( string $post_type ): bool {
        return post_type_exists( $post_type );
    }

    /**
     * Get posts by post type.
     *
     * @since 2.0.0
     * @param string $post_type Post type name.
     * @param int $limit Number of posts to get.
     * @return array
     */
    protected function get_posts_by_type( string $post_type, int $limit = -1 ): array {
        return get_posts( [
            'post_type' => $post_type,
            'numberposts' => $limit,
            'post_status' => 'any',
        ] );
    }

    /**
     * Count posts by post type.
     *
     * @since 2.0.0
     * @param string $post_type Post type name.
     * @return int
     */
    protected function count_posts_by_type( string $post_type ): int {
        return wp_count_posts( $post_type )->publish;
    }

    /**
     * Update post meta safely.
     *
     * @since 2.0.0
     * @param int $post_id Post ID.
     * @param string $meta_key Meta key.
     * @param mixed $meta_value Meta value.
     * @return bool
     */
    protected function update_post_meta_safe( int $post_id, string $meta_key, $meta_value ): bool {
        $result = update_post_meta( $post_id, $meta_key, $meta_value );

        if ( $result ) {
            $this->log( sprintf( 'Updated post meta: %s for post %d', $meta_key, $post_id ) );
        } else {
            $this->log( sprintf( 'Failed to update post meta: %s for post %d', $meta_key, $post_id ), 'warning' );
        }

        return $result;
    }

    /**
     * Update option safely.
     *
     * @since 2.0.0
     * @param string $option_name Option name.
     * @param mixed $option_value Option value.
     * @return bool
     */
    protected function update_option_safe( string $option_name, $option_value ): bool {
        $result = update_option( $option_name, $option_value );

        if ( $result ) {
            $this->log( sprintf( 'Updated option: %s', $option_name ) );
        } else {
            $this->log( sprintf( 'Failed to update option: %s', $option_name ), 'warning' );
        }

        return $result;
    }

    /**
     * Delete option safely.
     *
     * @since 2.0.0
     * @param string $option_name Option name.
     * @return bool
     */
    protected function delete_option_safe( string $option_name ): bool {
        $result = delete_option( $option_name );

        if ( $result ) {
            $this->log( sprintf( 'Deleted option: %s', $option_name ) );
        } else {
            $this->log( sprintf( 'Failed to delete option: %s', $option_name ), 'warning' );
        }

        return $result;
    }

}
