'use client';

import { useState, useEffect, useMemo } from 'react';
import {
  AreaChart,
  Area,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  ReferenceLine,
} from 'recharts';
import { TrendingDown, AlertCircle, Loader2, ChevronDown } from 'lucide-react';
import {
  DOMAIN_FRIENDLY,
  DOMAIN_COLORS,
  TimeRange,
  Granularity,
  URTDomain,
} from './types';

// ==================== Types ====================

interface TrendDataPoint {
  date: string;
  count: number;
  positive: number;
  negative: number;
  review_count: number;
  sentiment_score: number;  // -100 to +100
  // Rating impact - THE BUSINESS VALUE
  avg_rating_negative: number | null;  // Avg stars when complaints mention this category
  avg_rating_positive: number | null;  // Avg stars when praise mentions this category
}

interface TrendItem {
  id: string;
  label: string;
  color: string;
  data: TrendDataPoint[];
}

interface ExplorerViewProps {
  jobId?: string;
  businessId?: string;
}

// ==================== Constants ====================

const TIME_RANGE_OPTIONS: { value: TimeRange; label: string; description: string }[] = [
  { value: '7d', label: '7D', description: 'Last 7 days' },
  { value: '14d', label: '2W', description: 'Last 2 weeks' },
  { value: '30d', label: '1M', description: 'Last month' },
  { value: '90d', label: '3M', description: 'Last 3 months' },
  { value: '1y', label: '1Y', description: 'Last year' },
  { value: 'all', label: 'All', description: 'All time' },
];

const DOMAIN_OPTIONS: { value: URTDomain; label: string; emoji: string; color: string }[] = [
  { value: 'P', label: DOMAIN_FRIENDLY['P'].label, emoji: DOMAIN_FRIENDLY['P'].emoji, color: DOMAIN_COLORS['P'] },
  { value: 'V', label: DOMAIN_FRIENDLY['V'].label, emoji: DOMAIN_FRIENDLY['V'].emoji, color: DOMAIN_COLORS['V'] },
  { value: 'J', label: DOMAIN_FRIENDLY['J'].label, emoji: DOMAIN_FRIENDLY['J'].emoji, color: DOMAIN_COLORS['J'] },
  { value: 'O', label: DOMAIN_FRIENDLY['O'].label, emoji: DOMAIN_FRIENDLY['O'].emoji, color: DOMAIN_COLORS['O'] },
  { value: 'A', label: DOMAIN_FRIENDLY['A'].label, emoji: DOMAIN_FRIENDLY['A'].emoji, color: DOMAIN_COLORS['A'] },
  { value: 'E', label: DOMAIN_FRIENDLY['E'].label, emoji: DOMAIN_FRIENDLY['E'].emoji, color: DOMAIN_COLORS['E'] },
  { value: 'R', label: DOMAIN_FRIENDLY['R'].label, emoji: DOMAIN_FRIENDLY['R'].emoji, color: DOMAIN_COLORS['R'] },
];

// Metric options for dropdown
type MetricType = 'damage' | 'sentiment';
const METRIC_OPTIONS: { value: MetricType; label: string; description: string }[] = [
  { value: 'damage', label: '📉 Reputation Damage', description: 'Cumulative star loss from complaints' },
  { value: 'sentiment', label: '📊 Net Mentions', description: 'Positive minus negative (cumulative)' },
];

// Map time range to granularity
const getGranularity = (timeRange: TimeRange): Granularity => {
  switch (timeRange) {
    case '7d':
    case '14d':
      return 'day';
    case '30d':
      return 'week';
    case '90d':
      return 'week';
    case '1y':
      return 'month';
    case 'all':
      return 'month';
    default:
      return 'week';
  }
};

// ==================== Component ====================

const MAX_CATEGORIES = 4;

export function ExplorerView({ jobId, businessId }: ExplorerViewProps) {
  // State
  const [selectedCategories, setSelectedCategories] = useState<URTDomain[]>(['P', 'V']);
  const [selectedMetric, setSelectedMetric] = useState<MetricType>('damage');
  const [timeRange, setTimeRange] = useState<TimeRange>('1y');
  const [trendData, setTrendData] = useState<TrendItem[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isMetricOpen, setIsMetricOpen] = useState(false);

  // Fetch trend data when selection or time range changes
  useEffect(() => {
    if (selectedCategories.length === 0) {
      setTrendData([]);
      return;
    }

    const fetchTrendData = async () => {
      setIsLoading(true);
      setError(null);

      try {
        const granularity = getGranularity(timeRange);
        const itemsParam = selectedCategories.join(',');
        const url = `/api/pipelines/reviewiq/trends?job_id=${jobId}&items=${itemsParam}&time_range=${timeRange}&granularity=${granularity}`;

        const response = await fetch(url);

        if (!response.ok) {
          throw new Error(`Failed to fetch trend data: ${response.statusText}`);
        }

        const data: TrendItem[] = await response.json();
        setTrendData(data);
      } catch (err) {
        console.error('Error fetching trend data:', err);
        setError(err instanceof Error ? err.message : 'Failed to load trend data');
        setTrendData([]);
      } finally {
        setIsLoading(false);
      }
    };

    fetchTrendData();
  }, [jobId, selectedCategories, timeRange]);

  // Transform data for Recharts - calculate cumulative damage AND normalized sentiment
  const chartData = useMemo(() => {
    if (trendData.length === 0) return [];

    // Get all unique dates
    const dateSet = new Set<string>();
    trendData.forEach((item) => {
      item.data.forEach((d) => dateSet.add(d.date));
    });
    const dates = Array.from(dateSet).sort(
      (a, b) => new Date(a).getTime() - new Date(b).getTime()
    );

    // Track cumulative values per category
    const cumulatives: Record<string, {
      damage: number;
      totalPositive: number;
      totalNegative: number;
      totalCount: number;
    }> = {};
    trendData.forEach((item) => {
      cumulatives[item.id] = { damage: 0, totalPositive: 0, totalNegative: 0, totalCount: 0 };
    });

    // Build chart data with cumulative values for each category
    return dates.map((date) => {
      const point: Record<string, string | number | null> = { date };

      trendData.forEach((item) => {
        const dataPoint = item.data.find((d) => d.date === date);

        if (dataPoint) {
          // Damage: complaints * (5 - avg_rating)
          const avgRating = dataPoint.avg_rating_negative ?? 3;
          const periodDamage = dataPoint.negative * (5 - avgRating);
          cumulatives[item.id].damage += periodDamage;

          // Track totals for normalized sentiment
          cumulatives[item.id].totalPositive += dataPoint.positive;
          cumulatives[item.id].totalNegative += dataPoint.negative;
          cumulatives[item.id].totalCount += dataPoint.count;
        }

        // Damage as negative (going down like losses)
        point[`${item.id}_damage`] = -Math.round(cumulatives[item.id].damage * 10) / 10;

        // Net Mentions: cumulative (positive - negative) - preserves volume!
        const { totalPositive, totalNegative } = cumulatives[item.id];
        point[`${item.id}_sentiment`] = totalPositive - totalNegative;

        // Store period data for tooltips
        const dp = item.data.find((d) => d.date === date);
        point[`${item.id}_periodDamage`] = dp ? Math.round((dp.negative * (5 - (dp.avg_rating_negative ?? 3))) * 10) / 10 : 0;
        point[`${item.id}_complaints`] = dp?.negative ?? 0;
        point[`${item.id}_avgRating`] = dp?.avg_rating_negative ?? null;
        point[`${item.id}_periodSentiment`] = dp?.sentiment_score ?? 0;
      });

      return point;
    });
  }, [trendData]);

  // Toggle category selection
  const toggleCategory = (category: URTDomain) => {
    setSelectedCategories((prev) => {
      if (prev.includes(category)) {
        return prev.filter((c) => c !== category);
      }
      if (prev.length >= MAX_CATEGORIES) {
        return [...prev.slice(1), category];
      }
      return [...prev, category];
    });
  };

  // Format date for display
  const formatDate = (dateStr: string) => {
    const date = new Date(dateStr);
    const granularity = getGranularity(timeRange);

    switch (granularity) {
      case 'day':
        return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
      case 'week':
        return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
      case 'month':
        return date.toLocaleDateString('en-US', { month: 'short', year: '2-digit' });
      case 'year':
        return date.toLocaleDateString('en-US', { year: 'numeric' });
      default:
        return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
    }
  };

  const currentMetric = METRIC_OPTIONS.find(o => o.value === selectedMetric);

  return (
    <div className="bg-white rounded-xl p-6 shadow-md border-2 border-gray-200 hover:border-red-300 transition-all">
      {/* Header */}
      <div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
        <div className="flex items-start gap-3">
          <div className="p-2 bg-red-100 rounded-lg">
            <TrendingDown className="w-6 h-6 text-red-600" />
          </div>
          <div>
            <h3 className="text-xl font-bold text-gray-900">Reputation Tracker</h3>
            <p className="text-sm text-gray-500 mt-0.5">
              Compare cumulative damage across categories
            </p>
          </div>
        </div>

        {/* Time Range Selector */}
        <div className="flex items-center bg-gray-100 rounded-lg p-1">
          {TIME_RANGE_OPTIONS.map((opt) => (
            <button
              key={opt.value}
              onClick={() => setTimeRange(opt.value)}
              className={`px-2.5 py-1.5 text-xs font-semibold rounded-md transition-all ${
                timeRange === opt.value
                  ? 'bg-red-600 text-white shadow-sm'
                  : 'text-gray-600 hover:bg-gray-200'
              }`}
              title={opt.description}
            >
              {opt.label}
            </button>
          ))}
        </div>
      </div>

      {/* Category Chips + Metric Dropdown */}
      <div className="mb-6 space-y-3">
        {/* Category Toggle Chips */}
        <div className="flex flex-wrap gap-2">
          {DOMAIN_OPTIONS.map((opt) => {
            const isSelected = selectedCategories.includes(opt.value);
            return (
              <button
                key={opt.value}
                onClick={() => toggleCategory(opt.value)}
                className={`
                  flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
                  transition-all border-2
                  ${isSelected
                    ? 'shadow-md'
                    : 'border-gray-200 text-gray-500 hover:border-gray-300 hover:bg-gray-50'
                  }
                `}
                style={isSelected ? {
                  backgroundColor: `${opt.color}15`,
                  borderColor: opt.color,
                  color: opt.color,
                } : undefined}
              >
                <span className="text-base">{opt.emoji}</span>
                <span>{opt.label}</span>
              </button>
            );
          })}
        </div>

        {/* Metric Dropdown */}
        <div className="flex items-center gap-3">
          <span className="text-sm text-gray-500">Show:</span>
          <div className="relative">
            <button
              onClick={() => setIsMetricOpen(!isMetricOpen)}
              className="flex items-center gap-2 px-3 py-1.5 bg-gray-50 border border-gray-200 rounded-lg hover:border-gray-300 transition-all text-sm"
            >
              <span className="font-medium text-gray-700">{currentMetric?.label}</span>
              <ChevronDown className={`w-4 h-4 text-gray-400 transition-transform ${isMetricOpen ? 'rotate-180' : ''}`} />
            </button>

            {isMetricOpen && (
              <>
                <div className="fixed inset-0 z-10" onClick={() => setIsMetricOpen(false)} />
                <div className="absolute top-full left-0 mt-1 z-20 bg-white rounded-xl shadow-xl border border-gray-200 py-1 min-w-[250px]">
                  {METRIC_OPTIONS.map((opt) => (
                    <button
                      key={opt.value}
                      onClick={() => { setSelectedMetric(opt.value); setIsMetricOpen(false); }}
                      className={`w-full flex flex-col items-start px-4 py-2.5 hover:bg-gray-50 transition-colors ${
                        selectedMetric === opt.value ? 'bg-red-50' : ''
                      }`}
                    >
                      <span className="font-medium text-gray-700">{opt.label}</span>
                      <span className="text-xs text-gray-500">{opt.description}</span>
                    </button>
                  ))}
                </div>
              </>
            )}
          </div>

          <span className="text-xs text-gray-400 ml-auto">
            Select up to {MAX_CATEGORIES} categories to compare
          </span>
        </div>
      </div>

      {/* Chart Area */}
      <div className="relative">
        {/* Loading State */}
        {isLoading && (
          <div className="absolute inset-0 bg-white/80 z-10 flex items-center justify-center rounded-lg">
            <div className="flex items-center gap-3 text-red-600">
              <Loader2 className="w-6 h-6 animate-spin" />
              <span className="font-medium">Loading data...</span>
            </div>
          </div>
        )}

        {/* Error State */}
        {error && !isLoading && (
          <div className="flex flex-col items-center justify-center h-80 text-red-500">
            <AlertCircle className="w-12 h-12 mb-3" />
            <p className="font-medium mb-1">Failed to load data</p>
            <p className="text-sm text-gray-500">{error}</p>
          </div>
        )}

        {/* Empty State - No categories selected */}
        {!isLoading && !error && selectedCategories.length === 0 && (
          <div className="flex flex-col items-center justify-center h-80 text-gray-400">
            <TrendingDown className="w-12 h-12 mb-3" />
            <p className="font-medium mb-1">No categories selected</p>
            <p className="text-sm">Click categories above to compare their reputation impact</p>
          </div>
        )}

        {/* No Data State */}
        {!isLoading && !error && selectedCategories.length > 0 && chartData.length === 0 && (
          <div className="flex flex-col items-center justify-center h-80 text-gray-400">
            <TrendingDown className="w-12 h-12 mb-3" />
            <p className="font-medium mb-1">No data available</p>
            <p className="text-sm">Try selecting a different time range</p>
          </div>
        )}

        {/* Chart */}
        {!isLoading && !error && chartData.length > 0 && (
          <ResponsiveContainer width="100%" height={350}>
            <AreaChart
              data={chartData}
              margin={{ top: 10, right: 30, left: 0, bottom: 10 }}
            >
              <defs>
                {/* Generate gradients for each selected category */}
                {trendData.map((item) => (
                  <linearGradient key={`gradient-${item.id}`} id={`gradient-${item.id}`} x1="0" y1="0" x2="0" y2="1">
                    <stop offset="5%" stopColor={item.color} stopOpacity={0.3}/>
                    <stop offset="95%" stopColor={item.color} stopOpacity={0.05}/>
                  </linearGradient>
                ))}
              </defs>

              <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" vertical={false} />

              <XAxis
                dataKey="date"
                tick={{ fill: '#6b7280', fontSize: 11 }}
                tickLine={false}
                axisLine={{ stroke: '#e5e7eb' }}
                tickFormatter={formatDate}
                interval="preserveStartEnd"
              />

              <YAxis
                tick={{ fill: '#6b7280', fontSize: 11 }}
                tickLine={false}
                axisLine={false}
                tickFormatter={(value) => value.toFixed(0)}
              />

              {/* Center reference line at 0 */}
              <ReferenceLine y={0} stroke="#9ca3af" strokeDasharray="5 5" strokeWidth={1.5} />

              <Tooltip
                contentStyle={{
                  backgroundColor: '#ffffff',
                  border: 'none',
                  borderRadius: '12px',
                  boxShadow: '0 10px 40px rgba(0,0,0,0.15)',
                  padding: '16px',
                }}
                content={({ active, payload, label }) => {
                  if (active && payload && payload.length) {
                    const data = payload[0].payload;
                    return (
                      <div className="min-w-[240px]">
                        <p className="font-bold text-gray-900 mb-3 pb-2 border-b border-gray-100">
                          {formatDate(String(label))}
                        </p>

                        <div className="space-y-3">
                          {trendData.map((item) => {
                            const friendly = DOMAIN_FRIENDLY[item.id];
                            const value = data[`${item.id}_${selectedMetric}`];
                            const periodDamage = data[`${item.id}_periodDamage`];
                            const complaints = data[`${item.id}_complaints`];

                            return (
                              <div
                                key={item.id}
                                className="rounded-lg px-3 py-2 -mx-1"
                                style={{ backgroundColor: `${item.color}10` }}
                              >
                                <div className="flex items-center justify-between mb-1">
                                  <div className="flex items-center gap-2">
                                    <span>{friendly?.emoji}</span>
                                    <span className="text-sm font-semibold" style={{ color: item.color }}>
                                      {friendly?.label}
                                    </span>
                                  </div>
                                  <span className="font-bold" style={{ color: item.color }}>
                                    {typeof value === 'number' ? value.toFixed(0) : '-'}
                                  </span>
                                </div>
                                <div className="text-xs text-gray-500 flex gap-3">
                                  <span>Period: -{periodDamage} pts</span>
                                  <span>Complaints: {complaints}</span>
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    );
                  }
                  return null;
                }}
              />

              {/* Render area for each selected category */}
              {trendData.map((item) => (
                <Area
                  key={item.id}
                  type="monotone"
                  dataKey={`${item.id}_${selectedMetric}`}
                  name={item.label}
                  stroke={item.color}
                  strokeWidth={2.5}
                  fill={`url(#gradient-${item.id})`}
                  fillOpacity={0.6}
                  dot={false}
                  activeDot={{ r: 5, strokeWidth: 2, stroke: '#fff', fill: item.color }}
                />
              ))}
            </AreaChart>
          </ResponsiveContainer>
        )}
      </div>

      {/* Footer */}
      <div className="mt-4 pt-4 border-t border-gray-100">
        <p className="text-xs text-gray-500 text-center">
          {selectedMetric === 'damage'
            ? 'Each complaint costs points based on how low the rating is. Steeper drops = worse periods.'
            : 'Cumulative positive minus negative mentions. Above 0 = net positive. Categories with more volume show bigger swings.'
          }
        </p>
      </div>
    </div>
  );
}
