'use client';

import React from 'react';
import { DashboardElement, QueryResult } from '../types';
import { BarChartComponent } from './BarChartComponent';
import { PieChartComponent } from './PieChartComponent';
import { LineChartComponent } from './LineChartComponent';

interface ChartRendererProps {
  element: DashboardElement;
  data?: QueryResult;
  width?: number;
  height?: number;
}

/**
 * 차트 렌더러 컴포넌트
 * - 차트 타입에 따라 적절한 차트 컴포넌트를 렌더링
 * - 데이터 변환 및 에러 처리
 */
export function ChartRenderer({ element, data, width = 250, height = 200 }: ChartRendererProps) {
  // 데이터가 없거나 설정이 불완전한 경우
  if (!data || !element.chartConfig?.xAxis || !element.chartConfig?.yAxis) {
    return (
      <div className="w-full h-full flex items-center justify-center text-gray-500 text-sm">
        <div className="text-center">
          <div className="text-2xl mb-2">📊</div>
          <div>데이터를 설정해주세요</div>
          <div className="text-xs mt-1">⚙️ 버튼을 클릭하여 설정</div>
        </div>
      </div>
    );
  }

  // 데이터 변환
  const chartData = transformData(data, element.chartConfig);

  // 에러가 있는 경우
  if (chartData.length === 0) {
    return (
      <div className="w-full h-full flex items-center justify-center text-red-500 text-sm">
        <div className="text-center">
          <div className="text-2xl mb-2">⚠️</div>
          <div>데이터를 불러올 수 없습니다</div>
        </div>
      </div>
    );
  }

  // 차트 공통 props
  const chartProps = {
    data: chartData,
    config: element.chartConfig,
    width: width - 20, // 패딩 고려
    height: height - 60, // 헤더 높이 고려
  };

  // 차트 타입에 따른 렌더링
  switch (element.subtype) {
    case 'bar':
      return <BarChartComponent {...chartProps} />;
    case 'pie':
      return <PieChartComponent {...chartProps} />;
    case 'line':
      return <LineChartComponent {...chartProps} />;
    default:
      return (
        <div className="w-full h-full flex items-center justify-center text-gray-500 text-sm">
          <div className="text-center">
            <div className="text-2xl mb-2">❓</div>
            <div>지원하지 않는 차트 타입</div>
          </div>
        </div>
      );
  }
}

/**
 * 쿼리 결과를 차트 데이터로 변환
 */
function transformData(queryResult: QueryResult, config: any) {
  try {
    const { xAxis, yAxis, groupBy, aggregation = 'sum' } = config;
    
    if (!queryResult.rows || queryResult.rows.length === 0) {
      return [];
    }

    // 그룹핑이 있는 경우
    if (groupBy && groupBy !== xAxis) {
      const grouped = queryResult.rows.reduce((acc, row) => {
        const xValue = String(row[xAxis] || '');
        const groupValue = String(row[groupBy] || '');
        const yValue = Number(row[yAxis]) || 0;

        if (!acc[xValue]) {
          acc[xValue] = { [xAxis]: xValue };
        }

        if (!acc[xValue][groupValue]) {
          acc[xValue][groupValue] = 0;
        }

        // 집계 함수 적용
        switch (aggregation) {
          case 'sum':
            acc[xValue][groupValue] += yValue;
            break;
          case 'avg':
            // 평균 계산을 위해 임시로 배열 저장
            if (!acc[xValue][`${groupValue}_values`]) {
              acc[xValue][`${groupValue}_values`] = [];
            }
            acc[xValue][`${groupValue}_values`].push(yValue);
            break;
          case 'count':
            acc[xValue][groupValue] += 1;
            break;
          case 'max':
            acc[xValue][groupValue] = Math.max(acc[xValue][groupValue], yValue);
            break;
          case 'min':
            acc[xValue][groupValue] = Math.min(acc[xValue][groupValue], yValue);
            break;
        }

        return acc;
      }, {} as any);

      // 평균 계산 후처리
      if (aggregation === 'avg') {
        Object.keys(grouped).forEach(xValue => {
          Object.keys(grouped[xValue]).forEach(key => {
            if (key.endsWith('_values')) {
              const baseKey = key.replace('_values', '');
              const values = grouped[xValue][key];
              grouped[xValue][baseKey] = values.reduce((sum: number, val: number) => sum + val, 0) / values.length;
              delete grouped[xValue][key];
            }
          });
        });
      }

      return Object.values(grouped);
    }

    // 단순 변환 (그룹핑 없음)
    const dataMap = new Map();
    
    queryResult.rows.forEach(row => {
      const xValue = String(row[xAxis] || '');
      const yValue = Number(row[yAxis]) || 0;

      if (!dataMap.has(xValue)) {
        dataMap.set(xValue, { [xAxis]: xValue, [yAxis]: 0, count: 0 });
      }

      const existing = dataMap.get(xValue);
      
      switch (aggregation) {
        case 'sum':
          existing[yAxis] += yValue;
          break;
        case 'avg':
          existing[yAxis] += yValue;
          existing.count += 1;
          break;
        case 'count':
          existing[yAxis] += 1;
          break;
        case 'max':
          existing[yAxis] = Math.max(existing[yAxis], yValue);
          break;
        case 'min':
          existing[yAxis] = existing[yAxis] === 0 ? yValue : Math.min(existing[yAxis], yValue);
          break;
      }
    });

    // 평균 계산 후처리
    if (aggregation === 'avg') {
      dataMap.forEach(item => {
        if (item.count > 0) {
          item[yAxis] = item[yAxis] / item.count;
        }
        delete item.count;
      });
    }

    return Array.from(dataMap.values()).slice(0, 50); // 최대 50개 데이터포인트
  } catch (error) {
    console.error('데이터 변환 오류:', error);
    return [];
  }
}
