<?php

/**
 * Data Export Class
 *
 * Handles exporting plugin data to JSON or CSV format.
 *
 * @package    Karate_Club_Manager
 * @subpackage Karate_Club_Manager/includes/classes
 * @since      1.0.268
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
    // Exit if accessed directly.
}
/**
 * MACM Data Export Class
 *
 * Orchestrates data export operations.
 *
 * @since 1.0.268
 */
class MACM_Data_Export {
    /**
     * Export entities to the specified format.
     *
     * @since 1.0.268
     * @param array  $entities Array of entity keys to export.
     * @param string $format   Export format: 'json' or 'csv'.
     * @return array|WP_Error Export data array or error.
     */
    public function export_entities( $entities, $format = 'json' ) {
        if ( empty( $entities ) || !is_array( $entities ) ) {
            return new WP_Error('no_entities', __( 'No entities selected for export.', 'martial-arts-club-manager' ));
        }
        if ( 'json' === $format ) {
            return $this->export_to_json( $entities );
        }
        if ( 'csv' === $format ) {
            // CSV exports only support single entity at a time.
            $entity = reset( $entities );
            return $this->export_to_csv( $entity );
        }
        return new WP_Error('invalid_format', __( 'Invalid export format.', 'martial-arts-club-manager' ));
    }

    /**
     * Export entities to JSON format with metadata header.
     *
     * @since 1.0.268
     * @param array $entities Array of entity keys to export.
     * @return array Export data array with metadata.
     */
    public function export_to_json( $entities ) {
        $export_data = array(
            'macm_export' => $this->get_export_metadata( $entities ),
        );
        foreach ( $entities as $entity ) {
            $method = 'export_' . $entity;
            // Check for premium method.
            $premium_method = $method . '__premium_only';
            if ( method_exists( $this, $premium_method ) ) {
                // Premium entity - check license.
                if ( function_exists( 'macm_fs' ) && macm_fs()->can_use_premium_code() ) {
                    $export_data[$entity] = $this->{$premium_method}();
                }
            } elseif ( method_exists( $this, $method ) ) {
                // Free entity.
                $export_data[$entity] = $this->{$method}();
            }
        }
        return $export_data;
    }

    /**
     * Export a single entity to CSV format.
     *
     * @since 1.0.268
     * @param string $entity Entity key to export.
     * @return array|WP_Error Array with 'headers' and 'rows' or error.
     */
    public function export_to_csv( $entity ) {
        $method = 'export_' . $entity . '_csv';
        // Check for premium method.
        $premium_method = $method . '__premium_only';
        if ( method_exists( $this, $premium_method ) ) {
            if ( function_exists( 'macm_fs' ) && macm_fs()->can_use_premium_code() ) {
                return $this->{$premium_method}();
            }
            return new WP_Error('premium_required', __( 'Premium license required for this export.', 'martial-arts-club-manager' ));
        }
        if ( method_exists( $this, $method ) ) {
            return $this->{$method}();
        }
        // Fallback: Try JSON export and convert to CSV structure.
        $json_method = 'export_' . $entity;
        $json_premium_method = $json_method . '__premium_only';
        if ( method_exists( $this, $json_premium_method ) ) {
            if ( function_exists( 'macm_fs' ) && macm_fs()->can_use_premium_code() ) {
                $data = $this->{$json_premium_method}();
                return $this->convert_to_csv_structure( $data, $entity );
            }
            return new WP_Error('premium_required', __( 'Premium license required for this export.', 'martial-arts-club-manager' ));
        }
        if ( method_exists( $this, $json_method ) ) {
            $data = $this->{$json_method}();
            return $this->convert_to_csv_structure( $data, $entity );
        }
        return new WP_Error('invalid_entity', __( 'Invalid entity for export.', 'martial-arts-club-manager' ));
    }

    /**
     * Convert array data to CSV structure.
     *
     * @since 1.0.268
     * @param array  $data   Data array to convert.
     * @param string $entity Entity name for context.
     * @return array Array with 'headers' and 'rows'.
     */
    private function convert_to_csv_structure( $data, $entity ) {
        if ( empty( $data ) || !is_array( $data ) ) {
            return array(
                'headers' => array(),
                'rows'    => array(),
                'entity'  => $entity,
            );
        }
        // Get headers from first row.
        $first_row = reset( $data );
        $headers = ( is_array( $first_row ) ? array_keys( $first_row ) : array() );
        $rows = array();
        foreach ( $data as $row ) {
            if ( is_array( $row ) ) {
                $rows[] = array_values( $row );
            }
        }
        return array(
            'headers' => $headers,
            'rows'    => $rows,
            'entity'  => $entity,
        );
    }

    /**
     * Get export metadata header.
     *
     * @since 1.0.268
     * @param array $entities Array of entity keys being exported.
     * @return array Metadata array.
     */
    public function get_export_metadata( $entities = array() ) {
        return array(
            'version'           => MACM_VERSION,
            'format_version'    => '1.0',
            'exported_at'       => gmdate( 'c' ),
            'site_url'          => get_site_url(),
            'site_name'         => get_bloginfo( 'name' ),
            'entities_included' => $entities,
        );
    }

    // =========================================================================
    // FREE ENTITY EXPORT METHODS
    // =========================================================================
    /**
     * Export plugin settings to CSV format.
     *
     * Converts the flat key-value settings array to a proper CSV structure
     * with 'option_name' and 'option_value' columns.
     *
     * @since 1.0.281
     * @return array CSV structure with headers and rows.
     */
    public function export_settings_csv() {
        $settings = $this->export_settings();
        $headers = array('option_name', 'option_value');
        $rows = array();
        foreach ( $settings as $key => $value ) {
            // Convert arrays/objects to JSON string for CSV.
            if ( is_array( $value ) || is_object( $value ) ) {
                $value = wp_json_encode( $value );
            }
            $rows[] = array($key, $value);
        }
        return array(
            'headers' => $headers,
            'rows'    => $rows,
            'entity'  => 'settings',
        );
    }

    /**
     * Export plugin settings.
     *
     * @since 1.0.268
     * @return array Plugin settings.
     */
    public function export_settings() {
        $option_keys = array(
            'macm_version',
            'macm_db_version',
            'macm_button_gradient_start',
            'macm_button_gradient_end',
            'macm_trial_booking_page_id',
            'macm_member_area_page_id',
            'macm_class_register_page_id',
            'macm_events_page_id',
            'macm_training_videos_page_id',
            'macm_admin_email',
            'macm_woocommerce_integration'
        );
        /**
         * Filter the settings option keys to export.
         *
         * @since 1.0.268
         * @param array $option_keys Array of option keys.
         */
        $option_keys = apply_filters( 'macm_export_settings_keys', $option_keys );
        $settings = array();
        foreach ( $option_keys as $key ) {
            $value = get_option( $key );
            if ( false !== $value ) {
                $settings[$key] = $value;
            }
        }
        return $settings;
    }

    /**
     * Export belt colors to CSV format.
     *
     * @since 1.0.281
     * @return array CSV structure with headers and rows.
     */
    public function export_belt_colors_csv() {
        $data = $this->export_belt_colors();
        return $this->convert_to_csv_structure( $data, 'belt_colors' );
    }

    /**
     * Export belt colors.
     *
     * @since 1.0.268
     * @return array Belt colors data.
     */
    public function export_belt_colors() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $results = $wpdb->get_results( "SELECT id, color_key, color_name, sort_order, is_active, created_at\n\t\t\tFROM {$wpdb->prefix}macm_belt_colors\n\t\t\tORDER BY sort_order ASC", ARRAY_A );
        return ( $results ? $results : array() );
    }

    /**
     * Export membership types to CSV format.
     *
     * @since 1.0.281
     * @return array CSV structure with headers and rows.
     */
    public function export_membership_types_csv() {
        $data = $this->export_membership_types();
        return $this->convert_to_csv_structure( $data, 'membership_types' );
    }

    /**
     * Export membership types.
     *
     * @since 1.0.268
     * @return array Membership types data.
     */
    public function export_membership_types() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $results = $wpdb->get_results( "SELECT id, type_name, description, sort_order, is_active, created_at\n\t\t\tFROM {$wpdb->prefix}macm_membership_types\n\t\t\tORDER BY sort_order ASC", ARRAY_A );
        return ( $results ? $results : array() );
    }

    /**
     * Export members with user email for mapping.
     *
     * @since 1.0.268
     * @return array Members data with user emails.
     */
    public function export_members() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $members = $wpdb->get_results( "SELECT m.*, u.user_email, mt.type_name as membership_type_name\n\t\t\tFROM {$wpdb->prefix}macm_members m\n\t\t\tLEFT JOIN {$wpdb->users} u ON m.user_id = u.ID\n\t\t\tLEFT JOIN {$wpdb->prefix}macm_membership_types mt ON m.membership_type_id = mt.id\n\t\t\tORDER BY m.id ASC", ARRAY_A );
        if ( !$members ) {
            return array();
        }
        // Add group names for each member.
        foreach ( $members as &$member ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $groups = $wpdb->get_col( $wpdb->prepare( "SELECT g.group_name\n\t\t\t\t\tFROM {$wpdb->prefix}macm_member_groups mg\n\t\t\t\t\tJOIN {$wpdb->prefix}macm_groups g ON mg.group_id = g.id\n\t\t\t\t\tWHERE mg.member_id = %d", $member['id'] ) );
            $member['group_names'] = ( $groups ? implode( '|', $groups ) : '' );
        }
        return $members;
    }

    /**
     * Export members to CSV format.
     *
     * @since 1.0.268
     * @return array CSV structure with headers and rows.
     */
    public function export_members_csv() {
        $members = $this->export_members();
        $headers = array(
            'id',
            'user_email',
            'full_name',
            'date_of_birth',
            'membership_type_name',
            'belt_color',
            'group_names',
            'weight',
            'height',
            'license_number',
            'license_expiration',
            'status',
            'created_at'
        );
        $rows = array();
        foreach ( $members as $member ) {
            $rows[] = array(
                $member['id'],
                $member['user_email'] ?? '',
                $member['full_name'],
                $member['date_of_birth'],
                $member['membership_type_name'] ?? '',
                $member['belt_color'],
                $member['group_names'],
                $member['weight'],
                $member['height'],
                $member['license_number'] ?? '',
                $member['license_expiration'] ?? '',
                $member['status'],
                $member['created_at']
            );
        }
        return array(
            'headers' => $headers,
            'rows'    => $rows,
            'entity'  => 'members',
        );
    }

    /**
     * Export trial bookings to CSV format.
     *
     * @since 1.0.281
     * @return array CSV structure with headers and rows.
     */
    public function export_trial_bookings_csv() {
        $data = $this->export_trial_bookings();
        return $this->convert_to_csv_structure( $data, 'trial_bookings' );
    }

    /**
     * Export trial bookings.
     *
     * @since 1.0.268
     * @return array Trial bookings data.
     */
    public function export_trial_bookings() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $results = $wpdb->get_results( "SELECT tb.*, c.class_name\n\t\t\tFROM {$wpdb->prefix}macm_trial_bookings tb\n\t\t\tLEFT JOIN {$wpdb->prefix}macm_classes c ON tb.class_id = c.id\n\t\t\tORDER BY tb.id ASC", ARRAY_A );
        return ( $results ? $results : array() );
    }

    /**
     * Resolve an attachment ID to a photo entry for ZIP export.
     *
     * @since 1.0.319
     * @param int    $attachment_id WordPress attachment ID.
     * @param string $entity_type   Entity type (member, instructor, event).
     * @param int    $entity_id     Entity ID.
     * @return array|null Photo entry or null if not resolvable.
     */
    private function resolve_attachment_photo( $attachment_id, $entity_type, $entity_id ) {
        $file_path = get_attached_file( $attachment_id );
        if ( empty( $file_path ) || !file_exists( $file_path ) ) {
            return null;
        }
        $extension = strtolower( pathinfo( $file_path, PATHINFO_EXTENSION ) );
        if ( empty( $extension ) ) {
            return null;
        }
        return array(
            'zip_name'  => sprintf(
                'images/%s_%d.%s',
                $entity_type,
                $entity_id,
                $extension
            ),
            'file_path' => $file_path,
        );
    }

}
