// src/components/PriceHistoryChart.tsx
import React, { useState, useEffect, useMemo } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import * as apiClient from '../../services/apiClient';
import { LoadingSpinner } from '../../components/LoadingSpinner'; // This path is correct
import { useUserData } from '../../hooks/useUserData';
import type { HistoricalPriceDataPoint } from '../../types';

type HistoricalData = Record<string, { date: string; price: number }[]>;
type ChartData = { date: string; [itemName: string]: number | string };

const COLORS = ['#10B981', '#3B82F6', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899'];

export const PriceHistoryChart: React.FC = () => {
  const { watchedItems, isLoading: isLoadingUserData } = useUserData();
  const [historicalData, setHistoricalData] = useState<HistoricalData>({});
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const watchedItemsMap = useMemo(() => new Map(watchedItems.map(item => [item.master_grocery_item_id, item.name])), [watchedItems]);

  useEffect(() => {
    if (watchedItems.length === 0) {
        setIsLoading(false);
        setHistoricalData({}); // Clear data if watchlist becomes empty
        return;
    }

    const fetchData = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const watchedItemIds = watchedItems.map(item => item.master_grocery_item_id).filter((id): id is number => id !== undefined); // Ensure only numbers are passed
        const response = await apiClient.fetchHistoricalPriceData(watchedItemIds);
        const rawData: HistoricalPriceDataPoint[] = await response.json();
        if (rawData.length === 0) {
            setHistoricalData({});
            return;
        }

        const processedData = rawData.reduce<HistoricalData>((acc, record: HistoricalPriceDataPoint) => {
          if (!record.master_item_id || record.avg_price_in_cents === null || !record.summary_date) return acc;
          
          const itemName = watchedItemsMap.get(record.master_item_id);
          if (!itemName) return acc;

          const priceInCents = record.avg_price_in_cents;
          const date = new Date(`${record.summary_date}T00:00:00`).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
          
          if(priceInCents === 0) return acc;

          if (!acc[itemName]) {
            acc[itemName] = [];
          }

          // Ensure we only store the LOWEST price for a given day
          const existingEntryIndex = acc[itemName].findIndex(entry => entry.date === date);
          if (existingEntryIndex > -1) {
            if (priceInCents < acc[itemName][existingEntryIndex].price) {
                acc[itemName][existingEntryIndex].price = priceInCents;
            }
          } else {
            acc[itemName].push({ date, price: priceInCents });
          }

          return acc;
        }, {});
        
        // Filter out items that only have one data point for a meaningful trend line
        const filteredData = Object.entries(processedData).reduce<HistoricalData>((acc, [key, value]) => {
            if(value.length > 1){
                acc[key] = value.sort((a,b) => new Date(a.date).getTime() - new Date(b.date).getTime());
            }
            return acc;
        }, {});

        setHistoricalData(filteredData);
      } catch (e) {
        // This is a type-safe way to handle errors. We check if the caught
        // object is an instance of Error before accessing its message property.
        setError(e instanceof Error ? e.message : 'Failed to load price history.');
      } finally {
        setIsLoading(false);
      }
    };
    fetchData();
  }, [watchedItems, watchedItemsMap]);

  const chartData = useMemo<ChartData[]>(() => {
    const availableItems = Object.keys(historicalData);
    if (availableItems.length === 0) return [];
    
    const dateMap: Map<string, ChartData> = new Map();
    
    availableItems.forEach(itemName => {
      historicalData[itemName]?.forEach(({ date, price }) => {
        if (!dateMap.has(date)) {
          dateMap.set(date, { date });
        }
        // Store price in cents
        dateMap.get(date)![itemName] = price;
      });
    });

    return Array.from(dateMap.values()).sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
  }, [historicalData]);
  
  const availableItems = Object.keys(historicalData);

  const renderContent = () => {
    if (isLoading || isLoadingUserData) {
        return (
            <div role="status" className="flex justify-center items-center h-full min-h-[200px]">
                <LoadingSpinner /> <span className="ml-2">Loading Price History...</span>
            </div>
        );
    }
  
    if (error) {
        return (
            <div className="bg-red-100 dark:bg-red-900/50 border border-red-400 dark:border-red-600 text-red-700 dark:text-red-300 px-4 py-3 rounded-lg relative h-full flex items-center justify-center" role="alert">
                <p><strong>Error:</strong> {error}</p>
            </div>
        );
    }
  
    if (watchedItems.length === 0) {
        return (
            <div className="text-center py-8 h-full flex flex-col justify-center">
                <p className="text-gray-500 dark:text-gray-400">Add items to your watchlist to see their price trends over time.</p>
            </div>
        );
    }
    
    if (availableItems.length === 0) {
        return (
            <div className="text-center py-8 h-full flex flex-col justify-center">
                <p className="text-gray-500 dark:text-gray-400">Not enough historical data for your watched items. Process more flyers to build a trend.</p>
            </div>
        );
    }

    return (
        <ResponsiveContainer>
        <LineChart
            data={chartData}
            margin={{ top: 5, right: 20, left: -10, bottom: 5 }}
        >
            <CartesianGrid strokeDasharray="3 3" stroke="rgba(128, 128, 128, 0.2)" />
            <XAxis dataKey="date" tick={{ fill: '#9CA3AF', fontSize: 12 }} />
            <YAxis 
                tick={{ fill: '#9CA3AF', fontSize: 12 }} 
                tickFormatter={(value: number) => `$${(value / 100).toFixed(2)}`} 
                domain={[(a: number) => Math.floor(a * 0.95), (b: number) => Math.ceil(b * 1.05)]}
            />
            <Tooltip
                contentStyle={{
                    backgroundColor: 'rgba(31, 41, 55, 0.9)',
                    border: '1px solid #4B5563',
                    borderRadius: '0.5rem',
                }}
                labelStyle={{ color: '#F9FAFB' }}
                formatter={(value: number) => `$${(value / 100).toFixed(2)}`}
            />
            <Legend wrapperStyle={{fontSize: "12px"}} />
            {availableItems.map((item, index) => (
                <Line
                    key={item}
                    type="monotone"
                    dataKey={item}
                    stroke={COLORS[index % COLORS.length]}
                    strokeWidth={2}
                    dot={{ r: 4 }}
                    connectNulls
                />
            ))}
        </LineChart>
        </ResponsiveContainer>
    )
  }

  return (
    <div className="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
      <h3 className="text-lg font-semibold mb-4 text-gray-800 dark:text-white">Historical Price Trends</h3>
      <div style={{ width: '100%', height: 300 }}>
        {renderContent()}
      </div>
    </div>
  );
};