using LittleShop.Client;
using LittleShop.Client.Extensions;
using LittleShop.Client.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Text.Json;

// Setup dependency injection
var services = new ServiceCollection();

// Add logging
services.AddLogging(builder => builder
    .AddConsole()
    .SetMinimumLevel(LogLevel.Information));

// Add LittleShop client
services.AddLittleShopClient(options =>
{
    options.BaseUrl = "https://localhost:5001"; // Update this to your API URL
    options.TimeoutSeconds = 30;
    options.MaxRetryAttempts = 3;
    options.EnableLogging = true;
});

// Build service provider
var serviceProvider = services.BuildServiceProvider();

// Get the client
var client = serviceProvider.GetRequiredService<ILittleShopClient>();

Console.WriteLine("=== LittleShop Client Example ===\n");

try
{
    // Step 1: Authenticate
    Console.WriteLine("1. Authenticating...");
    var loginResult = await client.Authentication.LoginAsync("admin", "admin");
    
    if (!loginResult.IsSuccess)
    {
        Console.WriteLine($"Login failed: {loginResult.ErrorMessage}");
        return;
    }
    
    Console.WriteLine($"✓ Logged in as: {loginResult.Data!.Username}");
    Console.WriteLine($"  Token expires: {loginResult.Data.ExpiresAt}\n");
    
    // Step 2: Get Categories
    Console.WriteLine("2. Fetching categories...");
    var categoriesResult = await client.Catalog.GetCategoriesAsync();
    
    if (categoriesResult.IsSuccess && categoriesResult.Data!.Any())
    {
        Console.WriteLine($"✓ Found {categoriesResult.Data.Count} categories:");
        foreach (var category in categoriesResult.Data)
        {
            Console.WriteLine($"  - {category.Name}: {category.Description}");
        }
        Console.WriteLine();
    }
    
    // Step 3: Get Products
    Console.WriteLine("3. Fetching products...");
    var productsResult = await client.Catalog.GetProductsAsync(
        pageNumber: 1,
        pageSize: 5
    );
    
    if (productsResult.IsSuccess && productsResult.Data!.Items.Any())
    {
        Console.WriteLine($"✓ Found {productsResult.Data.TotalCount} products (showing first {productsResult.Data.Items.Count}):");
        foreach (var product in productsResult.Data.Items)
        {
            Console.WriteLine($"  - {product.Name}");
            Console.WriteLine($"    Price: £{product.Price:F2}");
            Console.WriteLine($"    Weight: {product.Weight} {product.WeightUnit}");
            Console.WriteLine($"    Category: {product.CategoryName}");
        }
        Console.WriteLine();
    }
    
    // Step 4: Create a sample order
    Console.WriteLine("4. Creating a sample order...");
    
    // Get first product for the order
    var firstProduct = productsResult.Data!.Items.FirstOrDefault();
    if (firstProduct != null)
    {
        var orderRequest = new CreateOrderRequest
        {
            IdentityReference = "CLIENT_DEMO_001",
            ShippingName = "Demo Customer",
            ShippingAddress = "123 Test Street",
            ShippingCity = "London",
            ShippingPostCode = "SW1A 1AA",
            ShippingCountry = "United Kingdom",
            Notes = "Test order from client SDK",
            Items = new List<CreateOrderItem>
            {
                new CreateOrderItem
                {
                    ProductId = firstProduct.Id,
                    Quantity = 1
                }
            }
        };
        
        var orderResult = await client.Orders.CreateOrderAsync(orderRequest);
        
        if (orderResult.IsSuccess)
        {
            Console.WriteLine($"✓ Order created successfully!");
            Console.WriteLine($"  Order ID: {orderResult.Data!.Id}");
            Console.WriteLine($"  Total: £{orderResult.Data.TotalAmount:F2}");
            Console.WriteLine($"  Status: {orderResult.Data.Status}\n");
            
            // Step 5: Create a payment for the order
            Console.WriteLine("5. Creating Bitcoin payment for the order...");
            var paymentResult = await client.Orders.CreatePaymentAsync(orderResult.Data.Id, "BTC");
            
            if (paymentResult.IsSuccess)
            {
                Console.WriteLine($"✓ Payment created successfully!");
                Console.WriteLine($"  Payment ID: {paymentResult.Data!.Id}");
                Console.WriteLine($"  Amount: {paymentResult.Data.RequiredAmount} BTC");
                Console.WriteLine($"  Send to: {paymentResult.Data.WalletAddress}");
                Console.WriteLine($"  Expires: {paymentResult.Data.ExpiresAt}");
                
                if (!string.IsNullOrEmpty(paymentResult.Data.BTCPayCheckoutUrl))
                {
                    Console.WriteLine($"  Checkout URL: {paymentResult.Data.BTCPayCheckoutUrl}");
                }
            }
            else
            {
                Console.WriteLine($"✗ Payment creation failed: {paymentResult.ErrorMessage}");
            }
        }
        else
        {
            Console.WriteLine($"✗ Order creation failed: {orderResult.ErrorMessage}");
        }
    }
    
    // Step 6: Get orders for the identity
    Console.WriteLine("\n6. Fetching orders for identity 'CLIENT_DEMO_001'...");
    var ordersResult = await client.Orders.GetOrdersByIdentityAsync("CLIENT_DEMO_001");
    
    if (ordersResult.IsSuccess && ordersResult.Data!.Any())
    {
        Console.WriteLine($"✓ Found {ordersResult.Data.Count} orders:");
        foreach (var order in ordersResult.Data)
        {
            Console.WriteLine($"  - Order {order.Id}");
            Console.WriteLine($"    Status: {order.Status}");
            Console.WriteLine($"    Total: £{order.TotalAmount:F2}");
            Console.WriteLine($"    Created: {order.CreatedAt}");
        }
    }
    else
    {
        Console.WriteLine("  No orders found for this identity.");
    }
    
    Console.WriteLine("\n=== Example completed successfully! ===");
}
catch (Exception ex)
{
    Console.WriteLine($"\n✗ Error: {ex.Message}");
    if (ex.InnerException != null)
    {
        Console.WriteLine($"  Inner: {ex.InnerException.Message}");
    }
}
finally
{
    // Cleanup
    client.Authentication.Logout();
    Console.WriteLine("\nLogged out.");
}