now the products images is shown at left and product is in right, make it similar to instagram post with like and comment buttons.
when user press like button app should inform the server that user liked the product.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert'; // For JSON decoding
import 'package:cached_network_image/cached_network_image.dart';

void main() {
  runApp(SearchApp());
}

class SearchApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Search App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SearchPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class Product {
  final String name;
  final String description;
  final String brand;
  final List categories;
  final Map hierarchicalCategories;
  final String type;
  final double price;
  final String priceRange;
  final String image;
  final String url;
  final bool freeShipping;
  final int popularity;
  final int rating;
  final String objectID;

  Product({
    required this.name,
    required this.description,
    required this.brand,
    required this.categories,
    required this.hierarchicalCategories,
    required this.type,
    required this.price,
    required this.priceRange,
    required this.image,
    required this.url,
    required this.freeShipping,
    required this.popularity,
    required this.rating,
    required this.objectID,
  });

  factory Product.fromJson(Map json) {
    List categoriesFromJson = [];
    if (json['categories'] != null) {
      categoriesFromJson = List.from(json['categories']);
    }

    Map hierarchicalCategoriesFromJson = {};
    if (json['hierarchicalCategories'] != null) {
      json['hierarchicalCategories'].forEach((key, value) {
        hierarchicalCategoriesFromJson[key] = value;
      });
    }

    return Product(
      name: json['name'] ?? '',
      description: json['description'] ?? '',
      brand: json['brand'] ?? '',
      categories: categoriesFromJson,
      hierarchicalCategories: hierarchicalCategoriesFromJson,
      type: json['type'] ?? '',
      price: (json['price'] as num?)?.toDouble() ?? 0.0,
      priceRange: json['price_range'] ?? '',
      image: json['image'] ?? '',
      url: json['url'] ?? '',
      freeShipping: json['free_shipping'] ?? false,
      popularity: json['popularity'] ?? 0,
      rating: json['rating'] ?? 0,
      objectID: json['objectID'] ?? '',
    );
  }
}

class SearchPage extends StatefulWidget {
  SearchPage({Key? key}) : super(key: key);

  @override
  _SearchPageState createState() => _SearchPageState();
}

class _SearchPageState extends State {
  final TextEditingController _controller = TextEditingController();
  List _searchResults = [];
  bool _isLoading = false;
  String _errorMessage = '';

  // Replace 'localhost' with your machine's IP address if running on a physical device
  final String _baseUrl = 'http://localhost:8000';

  Future _performSearch(String query) async {
    setState(() {
      _isLoading = true;
      _errorMessage = '';
      _searchResults = [];
    });

    final uri = Uri.parse('$_baseUrl/search').replace(queryParameters: {
      'query': query,
      'num': '50',
      'question': 'None',
    });

    try {
      final response = await http.get(uri);

      if (response.statusCode == 200) {
        // Parse JSON response
        final List data = json.decode(response.body);

        // Convert JSON to List
        List products =
            data.map((item) => Product.fromJson(item)).toList();

        setState(() {
          _searchResults = products;
        });
      } else {
        setState(() {
          _errorMessage = 'Error: ${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        _errorMessage = 'An error occurred: $e';
      });
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  void _onSearch() {
    final query = _controller.text.trim();
    if (query.isNotEmpty) {
      _performSearch(query);
    }
  }

  Widget _buildProductItem(Product product) {
    // Assuming images are served from the same base URL
    String imageUrl = '$_baseUrl/${product.image}';
    return Card(
      elevation: 3,
      margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
      child: ListTile(
        leading: CachedNetworkImage(
          imageUrl: imageUrl,
          placeholder: (context, url) =>
              const CircularProgressIndicator(), // Placeholder while loading
          errorWidget: (context, url, error) => const Icon(Icons.error),
          width: 60,
          height: 60,
          fit: BoxFit.cover,
        ),
        title: Text(product.name),
        subtitle: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(height: 4),
            Text(
              product.description,
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
            ),
            const SizedBox(height: 4),
            Text(
              'Brand: ${product.brand}',
              style: const TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 4),
            Text(
              'Price: \$${product.price.toStringAsFixed(2)}',
              style: TextStyle(color: Colors.green[700]),
            ),
            const SizedBox(height: 4),
            Row(
              children: List.generate(5, (index) {
                if (index < product.rating) {
                  return const Icon(Icons.star, color: Colors.orange, size: 16);
                } else {
                  return const Icon(Icons.star_border, color: Colors.orange, size: 16);
                }
              }),
            ),
          ],
        ),
        isThreeLine: true,
        onTap: () {
          // Optionally, handle tap to navigate to product URL
          // For example, using url_launcher package
        },
      ),
    );
  }

  Widget _buildResults() {
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator());
    } else if (_errorMessage.isNotEmpty) {
      return Center(
          child: Text(
        _errorMessage,
        style: const TextStyle(color: Colors.red),
      ));
    } else if (_searchResults.isEmpty) {
      return const Center(child: Text('No results found.'));
    } else {
      return Expanded(
        child: ListView.builder(
          itemCount: _searchResults.length,
          itemBuilder: (context, index) {
            return _buildProductItem(_searchResults[index]);
          },
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Search Products'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              Row(
                children: [
                  Expanded(
                    child: TextField(
                      controller: _controller,
                      decoration: const InputDecoration(
                        labelText: 'Search',
                        hintText: 'Enter search term',
                        border: OutlineInputBorder(),
                      ),
                      onSubmitted: (value) => _onSearch(),
                    ),
                  ),
                  const SizedBox(width: 8),
                  ElevatedButton(
                    onPressed: _onSearch,
                    child: const Text('Search'),
                  ),
                ],
              ),
              const SizedBox(height: 20),
              _buildResults(),
            ],
          ),
        ));
  }
}