<?php

declare(strict_types=1);

namespace App\Application\LiveComponents\ShoppingCart;

use App\Framework\LiveComponents\Attributes\LiveComponent;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentRenderData;

/**
 * ShoppingCartComponent - E-Commerce Warenkorb mit Live-Updates
 *
 * Demonstrates:
 * - Type-safe state management with ShoppingCartState Value Object
 * - Produkte hinzufügen/entfernen
 * - Mengen-Verwaltung mit Min/Max
 * - Automatische Preis-Berechnung
 * - Versandkosten-Berechnung
 * - Rabattcodes anwenden
 * - MwSt-Berechnung
 * - Bestandsprüfung
 * - Persistent Storage Support
 */
#[LiveComponent('shopping-cart')]
final readonly class ShoppingCartComponent implements LiveComponentContract
{
    public function __construct(
        public ComponentId $id,
        public ShoppingCartState $state
    ) {}

    public function getRenderData(): ComponentRenderData
    {
        // Prepare items for display
        $preparedItems = $this->prepareItemsForDisplay($this->state->items);

        // Calculate totals
        $subtotal = $this->state->getSubtotal();
        $discountAmount = $this->calculateDiscountAmount($subtotal, $this->state->discountPercentage);
        $subtotalAfterDiscount = $subtotal - $discountAmount;
        $shippingCost = $this->calculateShippingCost($this->state->shippingMethod, $subtotalAfterDiscount, $this->state->freeShippingThreshold);
        $taxAmount = $this->calculateTaxAmount($subtotalAfterDiscount + $shippingCost, $this->state->taxRate);
        $total = $subtotalAfterDiscount + $shippingCost + $taxAmount;

        // Prepare shipping options
        $shippingOptions = $this->prepareShippingOptions($this->state->shippingMethod);

        // Calculate savings
        $totalSavings = $discountAmount + ($shippingCost === 0 && $subtotalAfterDiscount >= $this->state->freeShippingThreshold ? $this->getStandardShippingCost() : 0);

        return new ComponentRenderData(
            templatePath: 'livecomponent-shopping-cart',
            data: [
                // Raw data
                'items' => $this->state->items,
                'discount_code' => $this->state->discountCode,
                'discount_percentage' => $this->state->discountPercentage,
                'shipping_method' => $this->state->shippingMethod,
                'tax_rate' => $this->state->taxRate,
                'currency' => $this->state->currency,

                // Display data
                'prepared_items' => $preparedItems,
                'item_count' => $this->state->getItemCount(),
                'total_quantity' => $this->state->getTotalQuantity(),
                'has_items' => $this->state->hasItems(),
                'is_empty' => ! $this->state->hasItems(),

                // Pricing
                'subtotal' => $subtotal,
                'subtotal_formatted' => $this->formatCurrency($subtotal, $this->state->currency),
                'discount_amount' => $discountAmount,
                'discount_amount_formatted' => $this->formatCurrency($discountAmount, $this->state->currency),
                'subtotal_after_discount' => $subtotalAfterDiscount,
                'subtotal_after_discount_formatted' => $this->formatCurrency($subtotalAfterDiscount, $this->state->currency),
                'shipping_cost' => $shippingCost,
                'shipping_cost_formatted' => $shippingCost === 0 ? 'Kostenlos' : $this->formatCurrency($shippingCost, $this->state->currency),
                'tax_amount' => $taxAmount,
                'tax_amount_formatted' => $this->formatCurrency($taxAmount, $this->state->currency),
                'total' => $total,
                'total_formatted' => $this->formatCurrency($total, $this->state->currency),
                'total_savings' => $totalSavings,
                'total_savings_formatted' => $this->formatCurrency($totalSavings, $this->state->currency),

                // Discount
                'has_discount' => $this->state->hasDiscount(),
                'discount_label' => $this->state->discountCode ? "Rabattcode: {$this->state->discountCode} (-{$this->state->discountPercentage}%)" : '',

                // Shipping
                'shipping_options' => $shippingOptions,
                'is_free_shipping' => $shippingCost === 0 && $subtotalAfterDiscount >= $this->state->freeShippingThreshold,
                'free_shipping_remaining' => max(0, $this->state->freeShippingThreshold - $subtotalAfterDiscount),
                'free_shipping_remaining_formatted' => $this->formatCurrency(max(0, $this->state->freeShippingThreshold - $subtotalAfterDiscount), $this->state->currency),
                'free_shipping_progress' => min(100, ($subtotalAfterDiscount / $this->state->freeShippingThreshold) * 100),

                // Validation
                'meets_minimum_order' => $subtotalAfterDiscount >= $this->state->minOrderValue,
                'minimum_order_remaining' => max(0, $this->state->minOrderValue - $subtotalAfterDiscount),
                'minimum_order_remaining_formatted' => $this->formatCurrency(max(0, $this->state->minOrderValue - $subtotalAfterDiscount), $this->state->currency),

                // Metadata
                'currency_symbol' => $this->getCurrencySymbol($this->state->currency),
                'tax_rate_percentage' => ($this->state->taxRate * 100),
            ]
        );
    }

    // Action methods - Type-safe parameters

    public function addItem(
        string $productId,
        string $productName,
        float $price,
        int $quantity = 1,
        ?string $imageUrl = null,
        array $attributes = []
    ): ShoppingCartState {
        return $this->state->withAddedItem(
            $productId,
            $productName,
            $price,
            $quantity,
            $imageUrl,
            $attributes
        );
    }

    public function removeItem(string $itemId): ShoppingCartState
    {
        return $this->state->withRemovedItem($itemId);
    }

    public function updateQuantity(string $itemId, int $newQuantity): ShoppingCartState
    {
        return $this->state->withUpdatedQuantity($itemId, $newQuantity);
    }

    public function applyDiscountCode(string $code): ShoppingCartState
    {
        // Simulate discount code validation
        $validCodes = [
            'WELCOME10' => 10,
            'SAVE20' => 20,
            'SUMMER15' => 15,
            'VIP25' => 25,
        ];

        $discountPercentage = $validCodes[strtoupper($code)] ?? 0;

        return $this->state->withDiscountCode($code, $discountPercentage);
    }

    public function removeDiscountCode(): ShoppingCartState
    {
        return $this->state->withoutDiscount();
    }

    public function changeShippingMethod(string $method): ShoppingCartState
    {
        return $this->state->withShippingMethod($method);
    }

    public function clearCart(): ShoppingCartState
    {
        return $this->state->clear();
    }

    // Helper methods

    private function prepareItemsForDisplay(array $items): array
    {
        return array_map(function ($item) {
            $itemTotal = $item['price'] * $item['quantity'];

            return [
                'id' => $item['id'],
                'product_id' => $item['product_id'],
                'product_name' => $item['product_name'],
                'price' => $item['price'],
                'price_formatted' => $this->formatCurrency($item['price'], $this->state->currency),
                'quantity' => $item['quantity'],
                'image_url' => $item['image_url'] ?? $this->getDefaultProductImage(),
                'attributes' => $item['attributes'],
                'attributes_display' => $this->formatAttributes($item['attributes']),
                'has_attributes' => ! empty($item['attributes']),
                'item_total' => $itemTotal,
                'item_total_formatted' => $this->formatCurrency($itemTotal, $this->state->currency),
                'can_increase' => $item['quantity'] < 99,
                'can_decrease' => $item['quantity'] > 1,
            ];
        }, $items);
    }

    private function calculateDiscountAmount(float $subtotal, int $discountPercentage): float
    {
        return $subtotal * ($discountPercentage / 100);
    }

    private function calculateShippingCost(string $method, float $subtotal, float $freeShippingThreshold): float
    {
        // Free shipping if threshold met
        if ($subtotal >= $freeShippingThreshold) {
            return 0;
        }

        return match ($method) {
            'standard' => 4.99,
            'express' => 9.99,
            'overnight' => 19.99,
            default => 4.99
        };
    }

    private function getStandardShippingCost(): float
    {
        return 4.99;
    }

    private function calculateTaxAmount(float $amount, float $taxRate): float
    {
        return $amount * $taxRate;
    }

    private function prepareShippingOptions(string $currentMethod): array
    {
        $options = [
            [
                'value' => 'standard',
                'label' => 'Standard (4-6 Werktage)',
                'cost' => 4.99,
                'cost_formatted' => '4,99 €',
                'is_selected' => $currentMethod === 'standard' ? 'selected' : '',
            ],
            [
                'value' => 'express',
                'label' => 'Express (2-3 Werktage)',
                'cost' => 9.99,
                'cost_formatted' => '9,99 €',
                'is_selected' => $currentMethod === 'express' ? 'selected' : '',
            ],
            [
                'value' => 'overnight',
                'label' => 'Overnight (1 Werktag)',
                'cost' => 19.99,
                'cost_formatted' => '19,99 €',
                'is_selected' => $currentMethod === 'overnight' ? 'selected' : '',
            ],
        ];

        return $options;
    }

    private function formatCurrency(float $amount, string $currency): string
    {
        $symbol = $this->getCurrencySymbol($currency);

        return number_format($amount, 2, ',', '.') . ' ' . $symbol;
    }

    private function getCurrencySymbol(string $currency): string
    {
        return match ($currency) {
            'EUR' => '€',
            'USD' => '$',
            'GBP' => '£',
            default => '€'
        };
    }

    private function getDefaultProductImage(): string
    {
        return 'https://via.placeholder.com/100x100/e0e0e0/666?text=Produkt';
    }

    private function formatAttributes(array $attributes): string
    {
        if (empty($attributes)) {
            return '';
        }

        $formatted = [];
        foreach ($attributes as $key => $value) {
            $formatted[] = ucfirst($key) . ': ' . $value;
        }

        return implode(', ', $formatted);
    }
}
