import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:provider/provider.dart';
import 'package:fl_chart/fl_chart.dart';
import '../providers/price_provider.dart';
import 'loading_screen.dart';

class PriceChart extends StatefulWidget {
  const PriceChart({super.key});

  @override
  State<PriceChart> createState() => _PriceChartState();
}

class _PriceChartState extends State<PriceChart> {
  double _yAxisMax = 0.001; // Default Y-axis maximum
  double _baseYAxisMax = 0.001; // Base maximum from data
  
  // X-axis zoom and pan state
  double _xZoomLevel = 1.0; // 1.0 = full view, 2.0 = 50% view, etc.
  double _xCenterPoint = 0.5; // 0.0 = leftmost, 1.0 = rightmost
  int _totalDataPoints = 0;

  static const timeRanges = [
    {'label': '6H', 'value': '6h'},
    {'label': '24H', 'value': '24h'},
    {'label': '3D', 'value': '3d'},
    {'label': '7D', 'value': '7d'},
    {'label': '1M', 'value': '1mo'},
    {'label': 'YTD', 'value': 'ytd'},
  ];

  static const colors = [
    Color(0xFF50E3C2), // Cyan
    Color(0xFFFF6B9D), // Pink
    Color(0xFFFFC658), // Yellow
    Color(0xFF82CA9D), // Green
    Color(0xFF8884D8), // Purple
    Color(0xFFFF7C7C), // Red
    Color(0xFFA28FD0), // Light Purple
    Color(0xFFF5A623), // Orange
    Color(0xFF4A90E2), // Blue
    Color(0xFF7ED321), // Lime
    Color(0xFFD0021B), // Dark Red
    Color(0xFFF8E71C), // Bright Yellow
  ];

  // Helper method to determine if hour marks should be shown
  bool _shouldShowHourMarks(List<int> visibleTimestamps) {
    if (visibleTimestamps.length < 2) return false;
    
    // Calculate time span of visible data
    final firstTime = DateTime.fromMillisecondsSinceEpoch(visibleTimestamps.first);
    final lastTime = DateTime.fromMillisecondsSinceEpoch(visibleTimestamps.last);
    final timeSpanHours = lastTime.difference(firstTime).inHours;
    
    // Show hour marks if viewing less than 3 days and zoomed in enough
    return timeSpanHours <= 72 && _xZoomLevel >= 2.0;
  }
  
  // Helper method to calculate appropriate X-axis interval
  double _calculateXAxisInterval(int visibleDataPoints) {
    if (visibleDataPoints <= 10) return 1.0;
    if (visibleDataPoints <= 50) return (visibleDataPoints / 5).ceilToDouble();
    if (visibleDataPoints <= 200) return (visibleDataPoints / 8).ceilToDouble();
    return (visibleDataPoints / 10).ceilToDouble();
  }
  
  // Helper method to calculate grid interval for vertical lines
  double _calculateGridInterval(List<int> visibleTimestamps) {
    if (visibleTimestamps.length <= 10) return 1.0;
    
    final showHours = _shouldShowHourMarks(visibleTimestamps);
    if (showHours) {
      // More frequent grid lines when showing hours
      return (visibleTimestamps.length / 12).ceilToDouble();
    } else {
      // Standard grid lines
      return (visibleTimestamps.length / 6).ceilToDouble();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: const Color(0xFF1A1F3A),
        borderRadius: BorderRadius.circular(4),
        border: Border.all(color: const Color(0xFF50E3C2), width: 1),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                'Price History',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'monospace',
                ),
              ),
              Consumer<PriceProvider>(
                builder: (context, provider, child) {
                  return Container(
                    height: 32,
                    decoration: BoxDecoration(
                      color: const Color(0xFF2A2F4A),
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(color: const Color(0xFF50E3C2), width: 1),
                    ),
                    child: DropdownButtonHideUnderline(
                      child: DropdownButton<String>(
                        value: provider.selectedRange,
                        dropdownColor: const Color(0xFF2A2F4A),
                        style: const TextStyle(
                          color: Colors.white,
                          fontSize: 12,
                          fontFamily: 'monospace',
                        ),
                        icon: const Icon(Icons.arrow_drop_down, color: Color(0xFF50E3C2)),
                        items: timeRanges.map((range) {
                          return DropdownMenuItem<String>(
                            value: range['value'],
                            child: Padding(
                              padding: const EdgeInsets.symmetric(horizontal: 12),
                              child: Text(
                                range['label']!,
                                style: const TextStyle(
                                  color: Colors.white,
                                  fontSize: 12,
                                  fontFamily: 'monospace',
                                ),
                              ),
                            ),
                          );
                        }).toList(),
                        onChanged: (String? newValue) {
                          if (newValue != null) {
                            provider.fetchHistory(newValue);
                          }
                        },
                      ),
                    ),
                  );
                },
              ),
            ],
          ),
          const SizedBox(height: 16),
          // Seller legend (Bloomberg style) - Vertical scrollable list
          Consumer<PriceProvider>(
            builder: (context, provider, child) {
              if (provider.historyData == null || provider.historyData!.prices.isEmpty) {
                return const SizedBox();
              }

              final sellers = provider.historyData!.prices
                  .map((p) => p.seller)
                  .toSet()
                  .toList();

              // Calculate needed height more precisely
              // Each seller name is ~10px font + 8px spacing = 18px per row
              // With wrap layout, calculate rows needed based on available width
              final screenWidth = MediaQuery.of(context).size.width;
              final availableWidth = screenWidth - 64; // Account for padding and margins
              
              // Estimate average seller name width (10px font * ~8 chars + dot + spacing = ~100px)
              final estimatedItemWidth = 100.0;
              final itemsPerRow = (availableWidth / estimatedItemWidth).floor().clamp(1, sellers.length);
              final rowsNeeded = (sellers.length / itemsPerRow).ceil();
              
              // Calculate height: rows * (font + spacing) + padding
              final neededHeight = (rowsNeeded * 18.0) + 16; // 16 for container padding
              final maxHeight = MediaQuery.of(context).size.height * 0.3; // Reduced to 30%
              final containerHeight = neededHeight.clamp(40.0, maxHeight); // Min 40px

              return Container(
                height: containerHeight,
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: const Color(0xFF2A2F4A), // Lighter gray background
                  borderRadius: BorderRadius.circular(4),
                ),
                child: Center(
                  child: Scrollbar(
                    thumbVisibility: containerHeight >= maxHeight, // Show scrollbar if content exceeds max height
                    child: SingleChildScrollView(
                      child: Wrap(
                        alignment: WrapAlignment.center,
                        crossAxisAlignment: WrapCrossAlignment.center,
                        spacing: 8, // Further reduced spacing
                        runSpacing: 2, // Further reduced vertical spacing
                        children: sellers.asMap().entries.map((entry) {
                          final index = entry.key;
                          final seller = entry.value;
                          final color = colors[index % colors.length];
                          
                          return Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Container(
                                width: 6, // Reduced from 8
                                height: 6, // Reduced from 8
                                decoration: BoxDecoration(
                                  color: color,
                                  shape: BoxShape.circle,
                                ),
                              ),
                              const SizedBox(width: 3), // Reduced from 4
                              Text(
                                seller,
                                style: TextStyle(
                                  color: color,
                                  fontSize: 9, // Reduced from 10 for more compact layout
                                  fontFamily: 'monospace',
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ],
                          );
                        }).toList(),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
          const SizedBox(height: 16),
          Consumer<PriceProvider>(
            builder: (context, provider, child) {
              if (provider.isHistoryLoading) {
                return const SizedBox(
                  height: 250,
                  child: LoadingScreen(
                    message: 'Loading chart data...',
                    showLogo: false,
                  ),
                );
              }
              
              if (provider.historyData == null || provider.historyData!.prices.isEmpty) {
                return const SizedBox(
                  height: 250,
                  child: Center(
                    child: Text(
                      'No chart data available',
                      style: TextStyle(color: Color(0xFF888888)),
                    ),
                  ),
                );
              }

              // Group prices by timestamp and seller
              final Map<int, Map<String, double>> groupedData = {};
              for (final price in provider.historyData!.prices) {
                final timestamp = price.timestamp.millisecondsSinceEpoch;
                groupedData.putIfAbsent(timestamp, () => {});
                groupedData[timestamp]![price.seller] = price.price;
              }

              // Convert to chart data
              final sortedTimestamps = groupedData.keys.toList()..sort();
              _totalDataPoints = sortedTimestamps.length;
              
              // Calculate X-axis view window based on zoom and center
              final viewWidth = (_totalDataPoints / _xZoomLevel).round();
              final centerIndex = (_xCenterPoint * _totalDataPoints).round();
              final startIndex = (centerIndex - viewWidth ~/ 2).clamp(0, _totalDataPoints - viewWidth);
              final endIndex = (startIndex + viewWidth).clamp(viewWidth, _totalDataPoints);
              
              final visibleTimestamps = sortedTimestamps.sublist(startIndex, endIndex);
              
              // Get unique sellers for line creation
              final sellers = provider.historyData!.prices
                  .map((p) => p.seller)
                  .toSet()
                  .toList();

              // Create line data for each seller (using visible timestamps)
              final lineBarsData = sellers.asMap().entries.map((entry) {
                final index = entry.key;
                final seller = entry.value;
                final color = colors[index % colors.length];
                
                final spots = <FlSpot>[];
                for (int i = 0; i < visibleTimestamps.length; i++) {
                  final timestamp = visibleTimestamps[i];
                  final price = groupedData[timestamp]![seller];
                  if (price != null) {
                    spots.add(FlSpot(i.toDouble(), price));
                  }
                }
                
                return LineChartBarData(
                  spots: spots,
                  isCurved: false,
                  color: color,
                  barWidth: 2,
                  isStrokeCapRound: false,
                  dotData: const FlDotData(show: false),
                );
              }).toList();

              // Calculate base Y-axis max from data
              final allPrices = provider.historyData!.prices.map((p) => p.price).toList();
              final maxPrice = allPrices.reduce((a, b) => a > b ? a : b);
              
              // Set base Y-axis max if not set
              if (_baseYAxisMax == 0.001) {
                _baseYAxisMax = maxPrice * 1.1; // Add 10% padding
                _yAxisMax = _baseYAxisMax;
              }

              // Calculate 65% of viewport height for the chart
              final screenHeight = MediaQuery.of(context).size.height;
              final chartHeight = screenHeight * 0.65;
              
              return Container(
                height: chartHeight,
                decoration: BoxDecoration(
                  color: const Color(0xFF0A0E27),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: GestureDetector(
                    onDoubleTap: () {
                      // Reset zoom on double tap
                      setState(() {
                        _yAxisMax = _baseYAxisMax;
                      });
                    },
                    child: NotificationListener<ScrollNotification>(
                      onNotification: (ScrollNotification notification) {
                        // Consume scroll notifications to prevent them from bubbling up
                        return true;
                      },
                      child: Listener(
                        onPointerSignal: (pointerSignal) {
                          if (pointerSignal is PointerScrollEvent) {
                            setState(() {
                              // Scroll up = zoom in (decrease Y max), scroll down = zoom out (increase Y max)
                              final delta = pointerSignal.scrollDelta.dy;
                              final zoomFactor = delta > 0 ? 1.1 : 0.9; // Zoom sensitivity
                              
                              _yAxisMax *= zoomFactor;
                              
                              // Clamp Y-axis max to reasonable bounds
                              final minY = maxPrice * 0.1; // Don't zoom in too much
                              final maxY = maxPrice * 10; // Don't zoom out too much
                              _yAxisMax = _yAxisMax.clamp(minY, maxY);
                            });
                          }
                        },
                      child: LineChart(
                        LineChartData(
                      backgroundColor: const Color(0xFF0A0E27),
                      minY: 0,
                      maxY: _yAxisMax,
                      gridData: FlGridData(
                        show: true,
                        drawVerticalLine: true,
                        verticalInterval: _calculateGridInterval(visibleTimestamps),
                        getDrawingHorizontalLine: (value) {
                          return FlLine(
                            color: const Color(0xFF2A2F4A),
                            strokeWidth: 1,
                          );
                        },
                        getDrawingVerticalLine: (value) {
                          // Different line styles based on zoom level
                          final showHours = _shouldShowHourMarks(visibleTimestamps);
                          return FlLine(
                            color: showHours ? const Color(0xFF3A3F5A) : const Color(0xFF2A2F4A),
                            strokeWidth: showHours ? 0.5 : 1,
                          );
                        },
                      ),
                      titlesData: FlTitlesData(
                        show: true,
                        rightTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false),
                        ),
                        topTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false),
                        ),
                        bottomTitles: AxisTitles(
                          sideTitles: SideTitles(
                            showTitles: true,
                            reservedSize: 45, // Reduced for more compact layout
                            interval: _calculateXAxisInterval(visibleTimestamps.length),
                            getTitlesWidget: (value, meta) {
                              if (value.toInt() >= visibleTimestamps.length) {
                                return const Text('');
                              }
                              final timestamp = visibleTimestamps[value.toInt()];
                              final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
                              
                              // Determine if we should show hour marks based on zoom level
                              final showHours = _shouldShowHourMarks(visibleTimestamps);
                              
                              return Padding(
                                padding: const EdgeInsets.only(top: 8),
                                child: Column(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    Text(
                                      '${date.month}/${date.day}',
                                      style: const TextStyle(
                                        color: Color(0xFF888888),
                                        fontSize: 10,
                                        fontFamily: 'monospace',
                                      ),
                                    ),
                                    if (showHours) ...[
                                      const SizedBox(height: 2),
                                      Text(
                                        '${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}',
                                        style: const TextStyle(
                                          color: Color(0xFF50E3C2),
                                          fontSize: 9,
                                          fontFamily: 'monospace',
                                          fontWeight: FontWeight.bold,
                                        ),
                                      ),
                                    ],
                                  ],
                                ),
                              );
                            },
                          ),
                        ),
                        leftTitles: AxisTitles(
                          sideTitles: SideTitles(
                            showTitles: MediaQuery.of(context).size.width > 600, // Hide on mobile
                            reservedSize: MediaQuery.of(context).size.width > 600 ? 70 : 0, // No space on mobile
                            getTitlesWidget: (value, meta) {
                              return Text(
                                value >= 1 ? '\$${value.toStringAsFixed(2)}' : 
                                value >= 0.01 ? '\$${value.toStringAsFixed(4)}' :
                                value >= 0.0001 ? '\$${value.toStringAsFixed(6)}' :
                                '\$${value.toStringAsFixed(8)}', // Use more decimal places instead of scientific notation
                                style: const TextStyle(
                                  color: Color(0xFF888888),
                                  fontSize: 9,
                                  fontFamily: 'monospace',
                                ),
                              );
                            },
                          ),
                        ),
                      ),
                      borderData: FlBorderData(
                        show: true,
                        border: Border.all(color: const Color(0xFF2A2F4A)),
                      ),
                      lineBarsData: lineBarsData,
                      clipData: const FlClipData.all(), // Clip chart lines to bounds
                      lineTouchData: LineTouchData(
                        enabled: true,
                        touchTooltipData: LineTouchTooltipData(
                          getTooltipColor: (touchedSpot) => const Color(0xFF2A2F4A),
                          tooltipRoundedRadius: 4,
                          tooltipPadding: const EdgeInsets.all(8),
                          tooltipMargin: 8,
                          fitInsideHorizontally: true,
                          fitInsideVertically: true,
                          rotateAngle: 0,
                          tooltipHorizontalAlignment: FLHorizontalAlignment.center,
                          tooltipHorizontalOffset: 0,
                          getTooltipItems: (List<LineBarSpot> touchedBarSpots) {
                            return touchedBarSpots.map((barSpot) {
                              final seller = sellers[barSpot.barIndex];
                              final price = barSpot.y;
                              final timestamp = visibleTimestamps[barSpot.x.toInt()];
                              final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
                              
                              return LineTooltipItem(
                                '$seller\n\$${price >= 1 ? price.toStringAsFixed(2) : price >= 0.01 ? price.toStringAsFixed(4) : price >= 0.0001 ? price.toStringAsFixed(6) : price.toStringAsFixed(8)}\n${date.month}/${date.day} ${date.hour}:${date.minute.toString().padLeft(2, '0')}',
                                TextStyle(
                                  color: colors[barSpot.barIndex % colors.length],
                                  fontWeight: FontWeight.bold,
                                  fontSize: 12,
                                  fontFamily: 'monospace',
                                ),
                              );
                            }).toList();
                          },
                        ),
                        touchCallback: (FlTouchEvent event, LineTouchResponse? touchResponse) {
                          // Handle touch events if needed
                        },
                        handleBuiltInTouches: true,
                      ),
                        ),
                        ),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
          const SizedBox(height: 12), // Reduced from 16
          // Timeline scrubber and controls (Bloomberg style)
          Consumer<PriceProvider>(
            builder: (context, provider, child) {
              if (provider.historyData == null || provider.historyData!.prices.isEmpty) {
                return const SizedBox();
              }

              // Get first and last timestamps for display
              final groupedData = <int, Map<String, double>>{};
              for (final price in provider.historyData!.prices) {
                final timestamp = price.timestamp.millisecondsSinceEpoch;
                groupedData.putIfAbsent(timestamp, () => {});
              }
              final sortedTimestamps = groupedData.keys.toList()..sort();
              
              final firstDate = DateTime.fromMillisecondsSinceEpoch(sortedTimestamps.first);
              final lastDate = DateTime.fromMillisecondsSinceEpoch(sortedTimestamps.last);

              return Column(
                children: [
                  // Timeline scrubber
                  Container(
                    height: 40,
                    padding: const EdgeInsets.symmetric(horizontal: 16),
                    decoration: BoxDecoration(
                      color: const Color(0xFF2A2F4A), // Lighter gray background
                      borderRadius: BorderRadius.circular(4),
                    ),
                    child: Row(
                      children: [
                        Text(
                          '${firstDate.month}/${firstDate.day}',
                          style: const TextStyle(
                            color: Color(0xFF888888),
                            fontSize: 10,
                            fontFamily: 'monospace',
                          ),
                        ),
                        Expanded(
                          child: Slider(
                            value: _xCenterPoint,
                            onChanged: (value) {
                              setState(() {
                                _xCenterPoint = value;
                              });
                            },
                            activeColor: const Color(0xFF50E3C2),
                            inactiveColor: const Color(0xFF1A1F3A),
                          ),
                        ),
                        Text(
                          '${lastDate.month}/${lastDate.day}',
                          style: const TextStyle(
                            color: Color(0xFF888888),
                            fontSize: 10,
                            fontFamily: 'monospace',
                          ),
                        ),
                      ],
                    ),
                  ),
                  const SizedBox(height: 8),
                  // Centered X-axis zoom controls
                  Center(
                    child: Wrap(
                      alignment: WrapAlignment.center,
                      crossAxisAlignment: WrapCrossAlignment.center,
                      spacing: 4, // Reduced spacing
                      runSpacing: 8,
                      children: [
                        // Zoom out button
                        IconButton(
                          onPressed: _xZoomLevel > 1.0 ? () {
                            setState(() {
                              _xZoomLevel = (_xZoomLevel / 1.5).clamp(1.0, 10.0);
                            });
                          } : null,
                          icon: const Icon(Icons.zoom_out, color: Color(0xFF50E3C2), size: 18), // Smaller icon
                          style: IconButton.styleFrom(
                            backgroundColor: const Color(0xFF2A2F4A),
                            disabledBackgroundColor: const Color(0xFF1A1F3A),
                            minimumSize: const Size(32, 32), // Smaller buttons
                          ),
                        ),
                        // Left navigation
                        IconButton(
                          onPressed: _xCenterPoint > 0.1 ? () {
                            setState(() {
                              final step = 0.1 / _xZoomLevel;
                              _xCenterPoint = (_xCenterPoint - step).clamp(0.0, 1.0);
                            });
                          } : null,
                          icon: const Icon(Icons.chevron_left, color: Color(0xFF50E3C2), size: 18),
                          style: IconButton.styleFrom(
                            backgroundColor: const Color(0xFF2A2F4A),
                            disabledBackgroundColor: const Color(0xFF1A1F3A),
                            minimumSize: const Size(32, 32),
                          ),
                        ),
                        // Zoom level indicator
                        Container(
                          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // More compact
                          decoration: BoxDecoration(
                            color: const Color(0xFF2A2F4A),
                            borderRadius: BorderRadius.circular(4),
                          ),
                          child: Text(
                            '${(_xZoomLevel * 100).toInt()}%',
                            style: const TextStyle(
                              color: Color(0xFF50E3C2),
                              fontSize: 10, // Smaller font
                              fontFamily: 'monospace',
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                        // Right navigation
                        IconButton(
                          onPressed: _xCenterPoint < 0.9 ? () {
                            setState(() {
                              final step = 0.1 / _xZoomLevel;
                              _xCenterPoint = (_xCenterPoint + step).clamp(0.0, 1.0);
                            });
                          } : null,
                          icon: const Icon(Icons.chevron_right, color: Color(0xFF50E3C2), size: 18),
                          style: IconButton.styleFrom(
                            backgroundColor: const Color(0xFF2A2F4A),
                            disabledBackgroundColor: const Color(0xFF1A1F3A),
                            minimumSize: const Size(32, 32),
                          ),
                        ),
                        // Zoom in button
                        IconButton(
                          onPressed: _xZoomLevel < 10.0 ? () {
                            setState(() {
                              _xZoomLevel = (_xZoomLevel * 1.5).clamp(1.0, 10.0);
                            });
                          } : null,
                          icon: const Icon(Icons.zoom_in, color: Color(0xFF50E3C2), size: 18),
                          style: IconButton.styleFrom(
                            backgroundColor: const Color(0xFF2A2F4A),
                            disabledBackgroundColor: const Color(0xFF1A1F3A),
                            minimumSize: const Size(32, 32),
                          ),
                        ),
                        // Reset button
                        ElevatedButton.icon(
                          onPressed: () {
                            setState(() {
                              _xZoomLevel = 1.0;
                              _xCenterPoint = 0.5;
                              _yAxisMax = _baseYAxisMax;
                            });
                          },
                          icon: const Icon(Icons.refresh, size: 14), // Smaller icon
                          label: const Text('Reset', style: TextStyle(fontSize: 10)), // Shorter text, smaller font
                          style: ElevatedButton.styleFrom(
                            backgroundColor: const Color(0xFF2A2F4A),
                            foregroundColor: const Color(0xFF50E3C2),
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // More compact
                            minimumSize: const Size(0, 32), // Smaller height
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              );
            },
          ),
        ],
      ),
    );
  }
}