<?php
/**
 * WishlistManager — wishlist operations for registered customers.
 *
 * Handles the tc_wishlists + tc_wishlist_items tables.
 * Each customer has one default wishlist (auto-created on first use).
 * Guest wishlists are not supported — redirect to login.
 *
 * @package TitanCart\Modules\Wishlist
 */

namespace TitanCart\Modules\Wishlist;

use TitanCart\Modules\Cart\CartManager;
use TitanCart\Services\SeoService;

defined( 'ABSPATH' ) || exit;

class WishlistManager {

    // ══════════════════════════════════════════════════════════════════════════
    // WISHLIST RECORD
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * Get or create the default wishlist for a customer.
     *
     * @param  int $customer_id  tc_customers.id
     * @return array  Wishlist row.
     */
    public function get_or_create( int $customer_id ): array {
        $db   = titancart_db();
        $row  = $db->getRow(
            "SELECT * FROM {$db->table('wishlists')} WHERE customer_id = ?i LIMIT 1",
            $customer_id
        );

        if ( $row ) {
            return $row;
        }

        // Create default wishlist.
        global $wpdb;
        $wpdb->insert( $wpdb->prefix . 'tc_wishlists', [
            'customer_id' => $customer_id,
            'name'        => __( 'My Wishlist', 'titancart-lite' ),
            'is_public'   => 0,
            'share_key'   => null,
            'created_at'  => current_time( 'mysql' ),
        ] );
        $wishlist_id = (int) $wpdb->insert_id;

        return $db->getRow(
            "SELECT * FROM {$db->table('wishlists')} WHERE id = ?i LIMIT 1",
            $wishlist_id
        );
    }

    /**
     * Find a wishlist by its public share key.
     *
     * @param  string $share_key
     * @return array|null
     */
    public function find_by_share_key( string $share_key ): ?array {
        $db  = titancart_db();
        $row = $db->getRow(
            "SELECT * FROM {$db->table('wishlists')} WHERE share_key = ?s AND is_public = 1 LIMIT 1",
            $share_key
        );
        return $row ?: null;
    }

    // ══════════════════════════════════════════════════════════════════════════
    // ITEM OPERATIONS
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * Add a product to the customer's wishlist.
     * Silently succeeds if the product is already in the list.
     *
     * @param  int      $customer_id
     * @param  int      $product_id
     * @param  int|null $variation_id
     * @return true|\WP_Error
     */
    public function add_item( int $customer_id, int $product_id, ?int $variation_id = null ) {
        $db       = titancart_db();
        $wishlist = $this->get_or_create( $customer_id );
        $wid      = (int) $wishlist['id'];

        // Already in list?
        $exists = $db->getField(
            "SELECT id FROM {$db->table('wishlist_items')}
             WHERE wishlist_id = ?i AND product_id = ?i LIMIT 1",
            $wid,
            $product_id
        );

        if ( $exists ) {
            return true; // idempotent
        }

        // Verify product exists and is active.
        $product = $db->getRow(
            "SELECT id, status FROM {$db->table('products')} WHERE id = ?i LIMIT 1",
            $product_id
        );
        if ( ! $product || $product['status'] !== 'active' ) {
            return new \WP_Error( 'invalid_product', __( 'Product not available.', 'titancart-lite' ) );
        }

        global $wpdb;
        $wpdb->insert( $wpdb->prefix . 'tc_wishlist_items', [
            'wishlist_id'  => $wid,
            'product_id'   => $product_id,
            'variation_id' => $variation_id,
            'added_at'     => current_time( 'mysql' ),
        ] );

        /**
         * Fires after an item is added to a wishlist.
         *
         * @param int      $product_id
         * @param int      $customer_id
         * @param int      $wishlist_id
         */
        do_action( 'titancart_wishlist_item_added', $product_id, $customer_id, $wid );

        return true;
    }

    /**
     * Remove a product from the customer's wishlist.
     *
     * @param  int $customer_id
     * @param  int $product_id
     * @return void
     */
    public function remove_item( int $customer_id, int $product_id ): void {
        $db       = titancart_db();
        $wishlist = $this->get_or_create( $customer_id );
        $wid      = (int) $wishlist['id'];

        global $wpdb;
        $wpdb->delete( $wpdb->prefix . 'tc_wishlist_items', [
            'wishlist_id' => $wid,
            'product_id'  => $product_id,
        ] );

        do_action( 'titancart_wishlist_item_removed', $product_id, $customer_id, $wid );
    }

    /**
     * Get paginated wishlist items with product data hydrated.
     *
     * @param  int $customer_id
     * @param  int $page
     * @param  int $per_page
     * @return array{ items: array, total: int, pages: int }
     */
    public function get_items( int $customer_id, int $page = 1, int $per_page = 20 ): array {
        $db       = titancart_db();
        $wishlist = $this->get_or_create( $customer_id );
        $wid      = (int) $wishlist['id'];
        $per_page = max( 1, $per_page );
        $page     = max( 1, $page );
        $offset   = ( $page - 1 ) * $per_page;

        $total = (int) $db->getField(
            "SELECT COUNT(*) FROM {$db->table('wishlist_items')} WHERE wishlist_id = ?i",
            $wid
        );

        $items = $db->getArray(
            "SELECT wi.id AS item_id, wi.product_id, wi.variation_id, wi.added_at,
                    p.status, p.price, p.list_price, p.slug, p.stock_quantity, p.stock_status,
                    COALESCE(pt.name, '') AS product_name
             FROM {$db->table('wishlist_items')} wi
             JOIN {$db->table('products')} p ON p.id = wi.product_id
             LEFT JOIN {$db->table('product_translations')} pt
               ON pt.product_id = p.id AND pt.language_code = 'en'
             WHERE wi.wishlist_id = ?i
             ORDER BY wi.added_at DESC
             LIMIT ?i OFFSET ?i",
            $wid,
            $per_page,
            $offset
        );

        // Attach thumbnail URL + catalog-effective price to each item.
        if ( ! empty( $items ) ) {
            // Catalog Promotions price-rewrite (#4 / KI-08, S271): decorate
            // price/list_price so the wishlist matches the shelf / PDP / cart.
            // Contract mirrors the card/PDP/StorefrontApiController (S270):
            //   price      ← effective (lowest of list-price sale, Bulk-Buys
            //                tier, matching catalog promo)
            //   list_price ← on_sale ? compare_at (regular/struck) : original
            // Behaviour-preserving when no catalog promo applies. Resolved at
            // quantity 1 for the viewing shopper; the row's own price/list_price
            // are the ?row fast-path so no extra SELECT per item. Gated on
            // class_exists so the wishlist degrades to raw prices if Promotions
            // is ever unavailable; the service is resolved once for the batch.
            $catalog_svc = class_exists( '\TitanCart\Modules\Promotions\CatalogPromotionService' )
                ? \TitanCart\Modules\Promotions\CatalogPromotionService::instance()
                : null;

            foreach ( $items as &$item ) {
                $att_id = $db->getField(
                    "SELECT wp_attachment_id
                     FROM {$db->table('product_images')}
                     WHERE product_id = ?i AND is_main = 1 LIMIT 1",
                    (int) $item['product_id']
                );
                $item['thumbnail_url'] = $att_id
                    ? ( wp_get_attachment_image_url( (int) $att_id, 'medium' ) ?: '' )
                    : '';
                $item['product_url']   = ! empty( $item['slug'] )
                    ? SeoService::product_url( $item['slug'] )
                    : '';

                if ( $catalog_svc ) {
                    $base_list = (float) ( $item['list_price'] ?? 0 );
                    $eff       = $catalog_svc->effective_price_for_viewer(
                        (int) $item['product_id'],
                        1,
                        [
                            'price'      => (float) ( $item['price'] ?? 0 ),
                            'list_price' => $base_list,
                        ]
                    );
                    $item['price']      = (float) $eff['price'];
                    $item['list_price'] = ( ! empty( $eff['on_sale'] ) && $eff['compare_at'] !== null )
                        ? (float) $eff['compare_at']
                        : $base_list;
                }
            }
            unset( $item );
        }

        return [
            'items' => $items ?: [],
            'total' => $total,
            'pages' => $total > 0 ? (int) ceil( $total / $per_page ) : 1,
        ];
    }

    /**
     * Check whether a product is in the customer's wishlist.
     *
     * @param  int $customer_id
     * @param  int $product_id
     * @return bool
     */
    public function is_in_wishlist( int $customer_id, int $product_id ): bool {
        $db       = titancart_db();
        $wishlist = $this->get_or_create( $customer_id );

        return (bool) $db->getField(
            "SELECT id FROM {$db->table('wishlist_items')}
             WHERE wishlist_id = ?i AND product_id = ?i LIMIT 1",
            (int) $wishlist['id'],
            $product_id
        );
    }

    /**
     * Get the total item count for the customer's wishlist.
     *
     * @param  int $customer_id
     * @return int
     */
    public function get_count( int $customer_id ): int {
        $db       = titancart_db();
        $wishlist = $this->get_or_create( $customer_id );

        return (int) $db->getField(
            "SELECT COUNT(*) FROM {$db->table('wishlist_items')} WHERE wishlist_id = ?i",
            (int) $wishlist['id']
        );
    }

    /**
     * Add a wishlist item to the cart (item stays in the wishlist).
     *
     * @param  int $customer_id
     * @param  int $product_id
     * @return true|\WP_Error
     */
    public function move_to_cart( int $customer_id, int $product_id ) {
        $cart_manager = new CartManager();
        $result       = $cart_manager->add_item( $product_id, 1 );

        if ( is_wp_error( $result ) ) {
            return $result;
        }

        do_action( 'titancart_wishlist_added_to_cart', $product_id, $customer_id );

        return true;
    }

    // ══════════════════════════════════════════════════════════════════════════
    // SHARING
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * Enable public sharing for a wishlist and return the share URL.
     *
     * @param  int $customer_id
     * @return string  Public URL.
     */
    public function enable_sharing( int $customer_id ): string {
        $wishlist = $this->get_or_create( $customer_id );

        $key = $wishlist['share_key'] ?? null;
        if ( ! $key ) {
            $key = wp_generate_password( 12, false );
            global $wpdb;
            $wpdb->update(
                $wpdb->prefix . 'tc_wishlists',
                [ 'is_public' => 1, 'share_key' => $key ],
                [ 'id' => (int) $wishlist['id'] ]
            );
        }

        return add_query_arg( 'tc_wishlist', $key, home_url( '/wishlist/' ) );
    }

    /**
     * Disable public sharing for a wishlist.
     *
     * @param  int $customer_id
     * @return void
     */
    public function disable_sharing( int $customer_id ): void {
        $wishlist = $this->get_or_create( $customer_id );
        global $wpdb;
        $wpdb->update(
            $wpdb->prefix . 'tc_wishlists',
            [ 'is_public' => 0, 'share_key' => null ],
            [ 'id' => (int) $wishlist['id'] ]
        );
    }
}
