"use client";

import React, { useState, useEffect } from "react";
import { DashboardHeader } from "@/components/layout/dashboard-header";
import { Button } from "@/components/ui/button";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { ChartConfigPanel } from "@/components/analytics/chart-config-panel";
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { channelsApi, analyticsApi } from "@/lib/api";
import { formatCurrency, formatNumber } from "@/lib/utils/format";
import { Plus, Loader2, AlertCircle, TrendingUp } from "lucide-react";
import type {
  TargetChannel,
  SpendingAnalytics,
  AnalyticsMetric,
  DateGrouping,
  SpendingDataPoint,
} from "@/lib/types/api";
import { format } from "date-fns";

interface ChartData {
  id: string;
  config: {
    targetChannelIds: string[];
    metrics: AnalyticsMetric[];
    dateFrom: Date | null;
    dateTo: Date | null;
    grouping: DateGrouping;
  };
  data: SpendingAnalytics | null;
  loading: boolean;
  width: "full" | "half";
}

// Компонент для sortable item
interface SortableChartItemProps {
  chart: ChartData;
  index: number;
  channels: TargetChannel[];
  chartsLength: number;
  onBuild: (chartId: string, config: ChartData["config"]) => void;
  onRemove: (chartId: string) => void;
  onWidthChange: (chartId: string, width: "full" | "half") => void;
}

const SortableChartItem: React.FC<SortableChartItemProps> = ({
  chart,
  index,
  channels,
  chartsLength,
  onBuild,
  onRemove,
  onWidthChange,
}) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: chart.id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };

  return (
    <div ref={setNodeRef} style={style} className={chart.width === "half" ? "" : "col-span-full"}>
      <ChartConfigPanel
        channels={channels}
        data={chart.data}
        loading={chart.loading}
        width={chart.width}
        onBuild={(config) => onBuild(chart.id, config)}
        onRemove={chartsLength > 1 ? () => onRemove(chart.id) : undefined}
        onWidthChange={(width) => onWidthChange(chart.id, width)}
        showRemoveButton={chartsLength > 1}
        chartNumber={index + 1}
        dragHandleProps={{ ...attributes, ...listeners }}
      />
    </div>
  );
};

export default function TargetChannelsAnalyticsPage() {
  const [channels, setChannels] = useState<TargetChannel[]>([]);
  const [charts, setCharts] = useState<ChartData[]>([
    {
      id: "chart-1",
      config: {
        targetChannelIds: [],
        metrics: [],
        dateFrom: null,
        dateTo: null,
        grouping: "day",
      },
      data: null,
      loading: false,
      width: "full",
    },
  ]);

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    loadChannels();
  }, []);

  const loadChannels = async () => {
    try {
      setLoading(true);
      const response = await channelsApi.list();
      const activeChannels = response.target_channels.filter((c) => c.is_active);
      setChannels(activeChannels);
    } catch (err: any) {
      setError(err?.error?.message || "Ошибка загрузки каналов");
    } finally {
      setLoading(false);
    }
  };

  const handleBuildChart = async (
    chartId: string,
    config: ChartData["config"]
  ) => {
    const chartIndex = charts.findIndex((c) => c.id === chartId);
    if (chartIndex === -1) return;

    // Обновляем состояние графика
    const updatedCharts = [...charts];
    updatedCharts[chartIndex].loading = true;
    updatedCharts[chartIndex].config = config;
    setCharts(updatedCharts);

    try {
      // Загружаем данные для каждого канала
      const promises = config.targetChannelIds.map((channelId) =>
        analyticsApi.spending({
          target_channel_id: channelId,
          date_from: config.dateFrom
            ? format(config.dateFrom, "yyyy-MM-dd'T'HH:mm:ss'Z'")
            : undefined,
          date_to: config.dateTo
            ? format(config.dateTo, "yyyy-MM-dd'T'HH:mm:ss'Z'")
            : undefined,
          grouping: config.grouping,
        })
      );

      const results = await Promise.all(promises);

      // Объединяем данные (если несколько каналов)
      const combinedData: SpendingAnalytics = results.reduce(
        (acc, result) => {
          acc.total_cost += result.total_cost;
          acc.total_subscriptions += result.total_subscriptions;
          acc.total_views += result.total_views;

          // Объединяем chart_data по периодам
          result.chart_data.forEach((dataPoint) => {
            const existing = acc.chart_data.find(
              (d) => d.period === dataPoint.period
            );
            if (existing) {
              existing.cost += dataPoint.cost;
              existing.subscriptions += dataPoint.subscriptions;
              existing.views += dataPoint.views;
              // CPF и CPM пересчитаем после
            } else {
              acc.chart_data.push({ ...dataPoint });
            }
          });

          return acc;
        },
        {
          total_cost: 0,
          total_subscriptions: 0,
          total_views: 0,
          avg_cpf: null,
          avg_cpm: null,
          chart_data: [] as SpendingDataPoint[],
        }
      );

      // Пересчитываем CPF и CPM для каждого периода
      combinedData.chart_data.forEach((dataPoint) => {
        dataPoint.cpf =
          dataPoint.subscriptions > 0
            ? dataPoint.cost / dataPoint.subscriptions
            : null;
        dataPoint.cpm =
          dataPoint.views > 0 ? (dataPoint.cost / dataPoint.views) * 1000 : null;
      });

      // Пересчитываем средние значения
      combinedData.avg_cpf =
        combinedData.total_subscriptions > 0
          ? combinedData.total_cost / combinedData.total_subscriptions
          : null;
      combinedData.avg_cpm =
        combinedData.total_views > 0
          ? (combinedData.total_cost / combinedData.total_views) * 1000
          : null;

      // Сортируем по периодам
      combinedData.chart_data.sort((a, b) =>
        a.period.localeCompare(b.period)
      );

      // Обновляем данные графика
      const finalCharts = [...updatedCharts];
      finalCharts[chartIndex].data = combinedData;
      finalCharts[chartIndex].loading = false;
      setCharts(finalCharts);
    } catch (err: any) {
      alert(err?.error?.message || "Ошибка загрузки данных");
      const finalCharts = [...updatedCharts];
      finalCharts[chartIndex].loading = false;
      setCharts(finalCharts);
    }
  };

  const handleAddChart = () => {
    setCharts([
      ...charts,
      {
        id: `chart-${Date.now()}`,
        config: {
          targetChannelIds: [],
          metrics: [],
          dateFrom: null,
          dateTo: null,
          grouping: "day",
        },
        data: null,
        loading: false,
        width: "full",
      },
    ]);
  };

  const handleRemoveChart = (chartId: string) => {
    if (charts.length === 1) {
      alert("Должен остаться хотя бы один график");
      return;
    }
    setCharts(charts.filter((c) => c.id !== chartId));
  };

  const handleWidthChange = (chartId: string, width: "full" | "half") => {
    setCharts(
      charts.map((chart) =>
        chart.id === chartId ? { ...chart, width } : chart
      )
    );
  };

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;

    if (over && active.id !== over.id) {
      setCharts((items) => {
        const oldIndex = items.findIndex((item) => item.id === active.id);
        const newIndex = items.findIndex((item) => item.id === over.id);

        return arrayMove(items, oldIndex, newIndex);
      });
    }
  };

  // Собираем все данные для таблицы
  const getAllTableData = (): SpendingDataPoint[] => {
    const allData: SpendingDataPoint[] = [];
    const periodMap = new Map<string, SpendingDataPoint>();

    charts.forEach((chart) => {
      if (!chart.data) return;
      chart.data.chart_data.forEach((dataPoint) => {
        const existing = periodMap.get(dataPoint.period);
        if (existing) {
          existing.cost += dataPoint.cost;
          existing.subscriptions += dataPoint.subscriptions;
          existing.views += dataPoint.views;
          // Пересчитываем CPF и CPM
          existing.cpf =
            existing.subscriptions > 0
              ? existing.cost / existing.subscriptions
              : null;
          existing.cpm =
            existing.views > 0 ? (existing.cost / existing.views) * 1000 : null;
        } else {
          periodMap.set(dataPoint.period, { ...dataPoint });
        }
      });
    });

    return Array.from(periodMap.values()).sort((a, b) =>
      a.period.localeCompare(b.period)
    );
  };

  const tableData = getAllTableData();

  if (loading) {
    return (
      <>
        <DashboardHeader
          breadcrumbs={[
            { label: "Аналитика", href: "/analytics" },
            { label: "Целевые каналы" },
          ]}
        />
        <div className="flex items-center justify-center p-12">
          <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
        </div>
      </>
    );
  }

  return (
    <>
      <DashboardHeader
        breadcrumbs={[
          { label: "Аналитика", href: "/analytics" },
          { label: "Целевые каналы" },
        ]}
      />
      <div className="flex flex-1 flex-col gap-4 p-4 pt-0 mt-4">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">
              Аналитика целевых каналов
            </h1>
            <p className="text-muted-foreground mt-1">
              Создайте графики для анализа показателей
            </p>
          </div>
          <Button onClick={handleAddChart}>
            <Plus className="mr-2 h-4 w-4" />
            Добавить график
          </Button>
        </div>

        {error && (
          <Alert variant="destructive">
            <AlertCircle className="h-4 w-4" />
            <AlertDescription>{error}</AlertDescription>
          </Alert>
        )}

        {channels.length === 0 ? (
          <Alert>
            <AlertCircle className="h-4 w-4" />
            <AlertDescription>
              Нет активных целевых каналов. Добавьте канал для начала работы с
              аналитикой.
            </AlertDescription>
          </Alert>
        ) : (
          <>
            {/* Графики */}
            <DndContext
              sensors={sensors}
              collisionDetection={closestCenter}
              onDragEnd={handleDragEnd}
            >
              <SortableContext
                items={charts.map((c) => c.id)}
                strategy={verticalListSortingStrategy}
              >
                <div className="grid grid-cols-2 gap-6">
                  {charts.map((chart, index) => (
                    <SortableChartItem
                      key={chart.id}
                      chart={chart}
                      index={index}
                      channels={channels}
                      chartsLength={charts.length}
                      onBuild={handleBuildChart}
                      onRemove={handleRemoveChart}
                      onWidthChange={handleWidthChange}
                    />
                  ))}
                </div>
              </SortableContext>
            </DndContext>

            {/* Таблица */}
            {tableData.length > 0 && (
              <Card>
                <CardHeader>
                  <CardTitle>Табличное представление</CardTitle>
                </CardHeader>
                <CardContent>
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>Период</TableHead>
                        <TableHead className="text-right">Расходы</TableHead>
                        <TableHead className="text-right">Подписки</TableHead>
                        <TableHead className="text-right">Просмотры</TableHead>
                        <TableHead className="text-right">CPF</TableHead>
                        <TableHead className="text-right">CPM</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {tableData.map((row) => (
                        <TableRow key={row.period}>
                          <TableCell className="font-medium">
                            {row.period}
                          </TableCell>
                          <TableCell className="text-right">
                            {formatCurrency(row.cost)}
                          </TableCell>
                          <TableCell className="text-right">
                            {formatNumber(row.subscriptions)}
                          </TableCell>
                          <TableCell className="text-right">
                            {formatNumber(row.views)}
                          </TableCell>
                          <TableCell className="text-right">
                            {row.cpf !== null ? formatCurrency(row.cpf) : "—"}
                          </TableCell>
                          <TableCell className="text-right">
                            {row.cpm !== null ? formatCurrency(row.cpm) : "—"}
                          </TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                </CardContent>
              </Card>
            )}
          </>
        )}
      </div>
    </>
  );
}

