import { useMemo, useState } from 'react';
import type { FeatureFilters, FeatureMeta, HexagonStatsResponse, PostcodeData } from '../types';
import type { HexagonLocation } from '../lib/external-search';
import { formatValue, calculateHistogramMean } from '../lib/format';
import { groupFeaturesByCategory } from '../lib/features';
import { STACKED_GROUPS } from '../lib/consts';
import { DualHistogram, LoadingSkeleton } from './DualHistogram';
import EnumBarChart from './EnumBarChart';
import StackedBarChart from './StackedBarChart';
import PriceHistoryChart from './PriceHistoryChart';
import ExternalSearchLinks from './ExternalSearchLinks';
import { InfoIcon, CloseIcon } from './ui/Icons';
import { IconButton } from './ui/IconButton';
import { FeatureInfoPopup } from './FeatureInfoPopup';
import { EmptyState } from './ui/EmptyState';

interface AreaPaneProps {
  stats: HexagonStatsResponse | null;
  globalFeatures: FeatureMeta[];
  loading: boolean;
  hexagonId: string | null;
  isPostcode?: boolean;
  postcodeData?: PostcodeData | null;
  onViewProperties: () => void;
  onClose: () => void;
  hexagonLocation: HexagonLocation | null;
  filters: FeatureFilters;
  onNavigateToSource?: (slug: string, featureName: string) => void;
}

export default function AreaPane({
  stats,
  globalFeatures,
  loading,
  hexagonId,
  isPostcode = false,
  postcodeData,
  onViewProperties,
  onClose,
  hexagonLocation,
  filters,
  onNavigateToSource,
}: AreaPaneProps) {
  // For postcodes, use local data for count
  const propertyCount = isPostcode && postcodeData ? postcodeData.count : stats?.count;
  const featureGroups = useMemo(() => groupFeaturesByCategory(globalFeatures), [globalFeatures]);
  const [infoFeature, setInfoFeature] = useState<FeatureMeta | null>(null);

  const numericByName = useMemo(() => {
    if (!stats) return new Map();
    return new Map(stats.numeric_features.map((feature) => [feature.name, feature]));
  }, [stats]);

  const enumByName = useMemo(() => {
    if (!stats) return new Map();
    return new Map(stats.enum_features.map((feature) => [feature.name, feature]));
  }, [stats]);

  const globalFeatureByName = useMemo(
    () => new Map(globalFeatures.map((f) => [f.name, f])),
    [globalFeatures]
  );

  if (!hexagonId) {
    return (
      <EmptyState
        icon={<InfoIcon className="w-8 h-8 text-warm-300 dark:text-warm-600" />}
        title="No area selected"
        description="Click a hexagon or postcode to view area statistics"
        centered
      />
    );
  }

  return (
    <div className="flex flex-col h-full">
      <div className="p-3 border-b border-warm-200 dark:border-navy-700">
        <div className="flex justify-between items-center">
          <div>
            <h2 className="text-sm font-semibold dark:text-warm-100">
              {isPostcode ? hexagonId : 'Area Statistics'}
            </h2>
            {isPostcode && (
              <span className="text-xs text-warm-500 dark:text-warm-400">Postcode</span>
            )}
          </div>
          <IconButton onClick={onClose} title="Close">
            <CloseIcon />
          </IconButton>
        </div>
        {propertyCount != null && (
          <p className="text-sm text-warm-600 dark:text-warm-400 mt-1">
            {propertyCount.toLocaleString()} properties
          </p>
        )}
        {!isPostcode && stats && (
          <button
            onClick={onViewProperties}
            className="mt-2 w-full text-sm py-1.5 rounded bg-teal-600 hover:bg-teal-700 text-white font-medium"
          >
            View {stats.count.toLocaleString()} Properties
          </button>
        )}
      </div>

      {hexagonLocation && stats && (
        <ExternalSearchLinks location={hexagonLocation} filters={filters} />
      )}

      <div className="flex-1 overflow-y-auto">
        {loading && !stats ? (
          <LoadingSkeleton />
        ) : stats ? (
          <div className="p-3 space-y-4">
            {stats.price_history && stats.price_history.length > 0 && (
              <div className="bg-warm-50 dark:bg-warm-800 rounded p-2">
                <span className="text-xs text-warm-700 dark:text-warm-300">Price History</span>
                <PriceHistoryChart points={stats.price_history} />
              </div>
            )}
            {featureGroups.map((group) => {
              const hasData = group.features.some(
                (feature) => numericByName.has(feature.name) || enumByName.has(feature.name)
              );
              if (!hasData) return null;

              const stackedCharts = STACKED_GROUPS[group.name];

              return (
                <div key={group.name}>
                  <h3 className="text-xs font-semibold text-warm-500 dark:text-warm-400 uppercase tracking-wider mb-2">
                    {group.name}
                  </h3>
                  <div className="space-y-3">
                    {stackedCharts
                      ? // Render stacked charts for this group
                        stackedCharts.map((chart) => {
                          const segments = chart.components
                            .map((name) => ({
                              name,
                              value: numericByName.get(name)?.mean ?? 0,
                            }))
                            .filter((s) => s.value > 0);

                          // Use aggregate feature stats if available, otherwise sum components
                          const aggregateStats = chart.feature
                            ? numericByName.get(chart.feature)
                            : undefined;
                          const total = aggregateStats
                            ? aggregateStats.mean
                            : segments.reduce((sum, s) => sum + s.value, 0);

                          const featureMeta = chart.feature
                            ? globalFeatureByName.get(chart.feature)
                            : undefined;

                          if (total === 0) return null;

                          return (
                            <div
                              key={chart.label}
                              className="bg-warm-50 dark:bg-warm-800 rounded p-2"
                            >
                              <div className="flex justify-between items-baseline mb-1.5">
                                <div className="flex items-center gap-1 min-w-0 mr-2">
                                  <span className="text-xs text-warm-700 dark:text-warm-300 truncate">
                                    {chart.label}
                                  </span>
                                  {featureMeta?.detail && (
                                    <button
                                      onClick={() => setInfoFeature(featureMeta)}
                                      className="text-warm-400 hover:text-warm-700 dark:hover:text-warm-300 shrink-0"
                                      title="Feature info"
                                    >
                                      <InfoIcon className="w-3 h-3" />
                                    </button>
                                  )}
                                </div>
                                <span className="text-xs font-semibold text-teal-700 dark:text-teal-400 whitespace-nowrap">
                                  {formatValue(total)}
                                  {chart.unit ? ` ${chart.unit}` : ''}
                                </span>
                              </div>
                              <StackedBarChart segments={segments} total={total} />
                            </div>
                          );
                        })
                      : // Default: render each feature individually
                        group.features.map((feature) => {
                          const numericStats = numericByName.get(feature.name);
                          const enumStats = enumByName.get(feature.name);

                          if (numericStats) {
                            const globalFeature = globalFeatureByName.get(feature.name);
                            const globalHistogram = globalFeature?.histogram;
                            const globalMean = globalHistogram
                              ? calculateHistogramMean(globalHistogram)
                              : undefined;

                            return (
                              <div
                                key={feature.name}
                                className="bg-warm-50 dark:bg-warm-800 rounded p-2"
                              >
                                <div className="flex justify-between items-baseline">
                                  <div className="flex items-center gap-1 min-w-0 mr-2">
                                    <span className="text-xs text-warm-700 dark:text-warm-300 truncate">
                                      {feature.name}
                                    </span>
                                    {feature.detail && (
                                      <button
                                        onClick={() => setInfoFeature(feature)}
                                        className="text-warm-400 hover:text-warm-700 dark:hover:text-warm-300 shrink-0"
                                        title="Feature info"
                                      >
                                        <InfoIcon className="w-3 h-3" />
                                      </button>
                                    )}
                                  </div>
                                  <span className="text-xs font-semibold text-teal-700 dark:text-teal-400 whitespace-nowrap">
                                    {formatValue(numericStats.mean)}
                                  </span>
                                </div>
                                {numericStats.histogram && (
                                  <>
                                    <div className="flex justify-between text-[10px] text-warm-400 dark:text-warm-500 mt-0.5">
                                      <span>{formatValue(numericStats.histogram.min)}</span>
                                      <span>{formatValue(numericStats.histogram.max)}</span>
                                    </div>
                                    {globalHistogram ? (
                                      <DualHistogram
                                        localCounts={numericStats.histogram.counts}
                                        globalCounts={globalHistogram.counts}
                                        min={numericStats.histogram.min}
                                        max={numericStats.histogram.max}
                                        globalMean={globalMean}
                                      />
                                    ) : (
                                      <DualHistogram
                                        localCounts={numericStats.histogram.counts}
                                        globalCounts={numericStats.histogram.counts}
                                        min={numericStats.histogram.min}
                                        max={numericStats.histogram.max}
                                      />
                                    )}
                                  </>
                                )}
                              </div>
                            );
                          }

                          if (enumStats) {
                            return (
                              <div
                                key={feature.name}
                                className="bg-warm-50 dark:bg-warm-800 rounded p-2"
                              >
                                <div className="flex items-center gap-1">
                                  <span className="text-xs text-warm-700 dark:text-warm-300">
                                    {feature.name}
                                  </span>
                                  {feature.detail && (
                                    <button
                                      onClick={() => setInfoFeature(feature)}
                                      className="text-warm-400 hover:text-warm-700 dark:hover:text-warm-300"
                                      title="Feature info"
                                    >
                                      <InfoIcon className="w-3 h-3" />
                                    </button>
                                  )}
                                </div>
                                <EnumBarChart counts={enumStats.counts} />
                              </div>
                            );
                          }

                          return null;
                        })}
                  </div>
                </div>
              );
            })}
          </div>
        ) : null}
      </div>

      {infoFeature && (
        <FeatureInfoPopup
          feature={infoFeature}
          onClose={() => setInfoFeature(null)}
          onNavigateToSource={onNavigateToSource}
        />
      )}
    </div>
  );
}
