import { BarChart, LineChart } from "@mantine/charts";
import "@mantine/charts/styles.css";
import {
  Area,
  AreaChart as RAreaChart,
  CartesianGrid,
  Legend,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import {
  Badge,
  Box,
  Center,
  Grid,
  Group,
  Loader,
  MultiSelect,
  Paper,
  Select,
  SimpleGrid,
  Stack,
  Table,
  Text,
  Title,
} from "@mantine/core";
import { DatePickerInput } from "@mantine/dates";
import "@mantine/dates/styles.css";
import {
  IconCheckbox,
  IconClipboardList,
  IconClockHour4,
  IconLock,
  IconTrendingUp,
} from "@tabler/icons-react";
import dayjs from "dayjs";
import { useEffect, useMemo, useState } from "react";
import * as api from "../api";
import type { Metrics, User } from "../types";
import { formatDuration } from "./format";

interface Props {
  users: User[];
}

function fmtDate(d: Date | null): string | undefined {
  if (!d) return undefined;
  return dayjs(d).format("YYYY-MM-DD");
}

function KPI({
  icon,
  label,
  value,
  hint,
  color,
}: {
  icon: React.ReactNode;
  label: string;
  value: string | number;
  hint?: string;
  color?: string;
}) {
  return (
    <Paper withBorder p="md" radius="md">
      <Stack gap={4}>
        <Group gap={6} c="dimmed">
          {icon}
          <Text size="xs" tt="uppercase" fw={600}>
            {label}
          </Text>
        </Group>
        <Text size="xl" fw={700} c={color}>
          {value}
        </Text>
        {hint && (
          <Text size="xs" c="dimmed">
            {hint}
          </Text>
        )}
      </Stack>
    </Paper>
  );
}

export function Dashboard({ users }: Props) {
  const [from, setFrom] = useState<Date | null>(() => dayjs().subtract(30, "day").toDate());
  const [to, setTo] = useState<Date | null>(() => new Date());
  const [assigneeId, setAssigneeId] = useState<string | null>(null);
  const [requester, setRequester] = useState<string | null>(null);
  const [tags, setTags] = useState<string[]>([]);
  const [tagOptions, setTagOptions] = useState<string[]>([]);
  const [data, setData] = useState<Metrics | null>(null);
  const [loading, setLoading] = useState(false);
  const [requesterOptions, setRequesterOptions] = useState<string[]>([]);

  useEffect(() => {
    api.listTags().then(setTagOptions).catch(() => {});
  }, []);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    api
      .getMetrics({
        from: fmtDate(from),
        to: fmtDate(to),
        assignee_id: assigneeId || undefined,
        requester: requester || undefined,
        tags: tags.length > 0 ? tags : undefined,
      })
      .then((m) => {
        if (cancelled) return;
        setData(m);
        setRequesterOptions((prev) => {
          const set = new Set(prev);
          for (const r of m.top_requesters ?? []) set.add(r.requester);
          return Array.from(set).sort();
        });
      })
      .catch(() => {})
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [from, to, assigneeId, requester, tags]);

  const userOptions = useMemo(
    () => users.map((u) => ({ value: u.id, label: u.display_name || u.username })),
    [users]
  );

  const cumulativeFlow = useMemo(() => {
    if (!data) return [];
    const arr = data.cumulative_flow ?? [];
    const firstIdx = arr.findIndex((p) => p.total > 0 || p.done > 0);
    const sliced = firstIdx <= 0 ? arr : arr.slice(Math.max(0, firstIdx - 1));
    return sliced.map((p) => ({
      date: p.date,
      done: p.done,
      wip: Math.max(0, p.total - p.done),
      total: p.total,
    }));
  }, [data]);

  const throughputSeries = useMemo(() => {
    if (!data) return [];
    const map = new Map<string, { date: string; completed: number; created: number }>();
    for (const d of data.throughput_daily ?? []) {
      map.set(d.date, { date: d.date, completed: d.count, created: 0 });
    }
    for (const d of data.created_daily ?? []) {
      const cur = map.get(d.date) ?? { date: d.date, completed: 0, created: 0 };
      cur.created = d.count;
      map.set(d.date, cur);
    }
    return Array.from(map.values()).sort((a, b) => a.date.localeCompare(b.date));
  }, [data]);

  const byColumnSeries = useMemo(() => {
    if (!data) return [];
    return (data.by_column ?? []).map((c) => ({
      column: c.name + (c.is_done ? " ✓" : ""),
      tarjetas: c.count,
    }));
  }, [data]);

  const topAssigneeSeries = useMemo(() => {
    if (!data) return [];
    return (data.top_assignees ?? [])
      .slice()
      .sort((a, b) => b.completed_in_range + b.active - (a.completed_in_range + a.active))
      .slice(0, 8)
      .map((a) => ({
        usuario: a.display_name || a.username,
        completadas: a.completed_in_range,
        activas: a.active,
      }));
  }, [data]);

  const topRequesterSeries = useMemo(() => {
    if (!data) return [];
    return (data.top_requesters ?? []).map((r) => ({
      solicitante: r.requester,
      activas: r.active,
      completadas: r.completed_in_range,
    }));
  }, [data]);

  const movementsSeries = useMemo(() => {
    if (!data) return [];
    return (data.movements_by_user ?? [])
      .filter((m) => m.moves > 0)
      .slice(0, 8)
      .map((m) => ({
        usuario: m.display_name || m.username,
        movimientos: m.moves,
      }));
  }, [data]);

  return (
    <Box p="md">
      <Stack gap="md">
        <Group justify="space-between">
          <Title order={3}>Dashboard</Title>
          <Group gap="xs" wrap="nowrap">
            <DatePickerInput
              label="Desde"
              value={from}
              onChange={(v) => setFrom(v as Date | null)}
              size="xs"
              clearable={false}
              valueFormat="YYYY-MM-DD"
              style={{ minWidth: 140 }}
            />
            <DatePickerInput
              label="Hasta"
              value={to}
              onChange={(v) => setTo(v as Date | null)}
              size="xs"
              clearable={false}
              valueFormat="YYYY-MM-DD"
              style={{ minWidth: 140 }}
            />
            <Select
              label="Asignado"
              size="xs"
              placeholder="Todos"
              value={assigneeId}
              onChange={setAssigneeId}
              data={userOptions}
              clearable
              searchable
              style={{ minWidth: 160 }}
            />
            <Select
              label="Solicitante"
              size="xs"
              placeholder="Todos"
              value={requester}
              onChange={setRequester}
              data={requesterOptions.map((r) => ({ value: r, label: r }))}
              clearable
              searchable
              style={{ minWidth: 160 }}
            />
            <MultiSelect
              label="Tags"
              size="xs"
              placeholder="Todas"
              value={tags}
              onChange={setTags}
              data={tagOptions}
              clearable
              searchable
              style={{ minWidth: 200 }}
            />
          </Group>
        </Group>

        {loading && !data && (
          <Center p="xl">
            <Loader />
          </Center>
        )}

        {data && (() => {
          const totals = data.totals ?? ({} as Metrics["totals"]);
          const lead = data.lead_time ?? ({ n: 0, avg_ms: 0, p50_ms: 0, p90_ms: 0, p99_ms: 0 } as Metrics["lead_time"]);
          const t = (k: keyof typeof totals) => totals[k] ?? 0;
          return (
          <>
            <SimpleGrid cols={{ base: 2, md: 5 }} spacing="md">
              <KPI
                icon={<IconClipboardList size={14} />}
                label="Totales"
                value={t("cards")}
                hint={`${t("columns")} columnas, ${t("users")} usuarios`}
              />
              <KPI
                icon={<IconClipboardList size={14} />}
                label="Activas"
                value={t("cards_active")}
                hint={`Sin completar`}
                color="blue"
              />
              <KPI
                icon={<IconCheckbox size={14} />}
                label="Completadas (rango)"
                value={t("cards_completed_in_range")}
                hint={`${t("cards_done")} completadas total · ${t("cards_created_in_range")} creadas rango`}
                color="green"
              />
              <KPI
                icon={<IconClockHour4 size={14} />}
                label="Lead time p50"
                value={lead.n > 0 ? formatDuration(lead.p50_ms) : 0}
                hint={`p90 ${lead.n > 0 ? formatDuration(lead.p90_ms) : 0} · n=${lead.n}`}
              />
              <KPI
                icon={<IconLock size={14} />}
                label="Bloqueos activos"
                value={t("active_locks")}
                hint={`Total bloqueado: ${formatDuration(data.lock_total_ms ?? 0)}`}
                color={t("active_locks") > 0 ? "yellow" : undefined}
              />
            </SimpleGrid>

            <Paper withBorder p="md" radius="md">
              <Group gap={6} mb="sm">
                <IconTrendingUp size={16} />
                <Text fw={600}>Cumulative Flow Diagram</Text>
                <Text size="xs" c="dimmed">
                  total vs hechas (acumulado)
                </Text>
              </Group>
              {cumulativeFlow.length === 0 ? (
                <Text c="dimmed" size="sm">
                  Sin datos.
                </Text>
              ) : (
                <div style={{ height: 260, width: "100%" }}>
                  <ResponsiveContainer width="100%" height="100%">
                    <RAreaChart data={cumulativeFlow} margin={{ top: 10, right: 16, left: 0, bottom: 0 }}>
                      <CartesianGrid strokeDasharray="5 5" stroke="var(--mantine-color-gray-4)" />
                      <XAxis dataKey="date" tick={{ fontSize: 12, fill: "currentColor" }} />
                      <YAxis allowDecimals={false} tick={{ fontSize: 12, fill: "currentColor" }} />
                      <Tooltip
                        contentStyle={{
                          background: "var(--mantine-color-body)",
                          border: "1px solid var(--mantine-color-gray-3)",
                          borderRadius: 6,
                          fontSize: 12,
                        }}
                      />
                      <Legend wrapperStyle={{ fontSize: 12 }} />
                      <Area
                        type="linear"
                        dataKey="done"
                        name="Hechas"
                        stackId="cfd"
                        stroke="var(--mantine-color-green-6)"
                        fill="var(--mantine-color-green-6)"
                        fillOpacity={0.55}
                        strokeWidth={2}
                        isAnimationActive={false}
                        dot={{ r: 3, fill: "var(--mantine-color-green-6)", strokeWidth: 0 }}
                        activeDot={{ r: 5 }}
                      />
                      <Area
                        type="linear"
                        dataKey="wip"
                        name="En curso"
                        stackId="cfd"
                        stroke="var(--mantine-color-blue-6)"
                        fill="var(--mantine-color-blue-6)"
                        fillOpacity={0.55}
                        strokeWidth={2}
                        isAnimationActive={false}
                        dot={{ r: 3, fill: "var(--mantine-color-blue-6)", strokeWidth: 0 }}
                        activeDot={{ r: 5 }}
                      />
                    </RAreaChart>
                  </ResponsiveContainer>
                </div>
              )}
            </Paper>

            <Grid>
              <Grid.Col span={{ base: 12, md: 8 }}>
                <Paper withBorder p="md" radius="md">
                  <Group gap={6} mb="sm">
                    <IconTrendingUp size={16} />
                    <Text fw={600}>Throughput diario</Text>
                  </Group>
                  {throughputSeries.length === 0 ? (
                    <Text c="dimmed" size="sm">
                      Sin datos en el rango.
                    </Text>
                  ) : (
                    <LineChart
                      h={240}
                      data={throughputSeries}
                      dataKey="date"
                      curveType="monotone"
                      withLegend
                      series={[
                        { name: "completed", label: "Completadas", color: "green.6" },
                        { name: "created", label: "Creadas", color: "blue.6" },
                      ]}
                    />
                  )}
                </Paper>
              </Grid.Col>
              <Grid.Col span={{ base: 12, md: 4 }}>
                <Paper withBorder p="md" radius="md">
                  <Text fw={600} mb="sm">
                    Tarjetas por columna
                  </Text>
                  {byColumnSeries.length === 0 ? (
                    <Text c="dimmed" size="sm">
                      Sin columnas.
                    </Text>
                  ) : (
                    <BarChart
                      h={240}
                      data={byColumnSeries}
                      dataKey="column"
                      orientation="vertical"
                      yAxisProps={{ width: 100 }}
                      series={[{ name: "tarjetas", label: "Tarjetas", color: "blue.6" }]}
                    />
                  )}
                </Paper>
              </Grid.Col>
            </Grid>

            <Grid>
              <Grid.Col span={{ base: 12, md: 6 }}>
                <Paper withBorder p="md" radius="md">
                  <Text fw={600} mb="sm">
                    Top asignados
                  </Text>
                  {topAssigneeSeries.length === 0 ? (
                    <Text c="dimmed" size="sm">
                      Sin asignaciones.
                    </Text>
                  ) : (
                    <BarChart
                      h={240}
                      data={topAssigneeSeries}
                      dataKey="usuario"
                      orientation="vertical"
                      yAxisProps={{ width: 120 }}
                      withLegend
                      series={[
                        { name: "completadas", label: "Completadas", color: "green.6" },
                        { name: "activas", label: "Activas", color: "blue.6" },
                      ]}
                      type="stacked"
                    />
                  )}
                </Paper>
              </Grid.Col>
              <Grid.Col span={{ base: 12, md: 6 }}>
                <Paper withBorder p="md" radius="md">
                  <Text fw={600} mb="sm">
                    Top solicitantes
                  </Text>
                  {topRequesterSeries.length === 0 ? (
                    <Text c="dimmed" size="sm">
                      Sin solicitantes en el rango.
                    </Text>
                  ) : (
                    <BarChart
                      h={Math.max(240, topRequesterSeries.length * 32)}
                      data={topRequesterSeries}
                      dataKey="solicitante"
                      orientation="vertical"
                      yAxisProps={{ width: 160, interval: 0 }}
                      withLegend
                      series={[
                        { name: "completadas", label: "Completadas", color: "green.6" },
                        { name: "activas", label: "Activas", color: "violet.6" },
                      ]}
                      type="stacked"
                    />
                  )}
                </Paper>
              </Grid.Col>
            </Grid>

            <Grid>
              <Grid.Col span={{ base: 12, md: 6 }}>
                <Paper withBorder p="md" radius="md">
                  <Text fw={600} mb="sm">
                    Movimientos por usuario (rango)
                  </Text>
                  {movementsSeries.length === 0 ? (
                    <Text c="dimmed" size="sm">
                      Sin movimientos registrados.
                    </Text>
                  ) : (
                    <BarChart
                      h={240}
                      data={movementsSeries}
                      dataKey="usuario"
                      orientation="vertical"
                      yAxisProps={{ width: 120 }}
                      series={[{ name: "movimientos", label: "Movimientos", color: "orange.6" }]}
                    />
                  )}
                </Paper>
              </Grid.Col>
              <Grid.Col span={{ base: 12, md: 6 }}>
                <Paper withBorder p="md" radius="md">
                  <Text fw={600} mb="sm">
                    Tiempo en columna (cycle time)
                  </Text>
                  <Table striped highlightOnHover withTableBorder withColumnBorders fz="xs">
                    <Table.Thead>
                      <Table.Tr>
                        <Table.Th>Columna</Table.Th>
                        <Table.Th>n</Table.Th>
                        <Table.Th>p50</Table.Th>
                        <Table.Th>p90</Table.Th>
                        <Table.Th>avg</Table.Th>
                      </Table.Tr>
                    </Table.Thead>
                    <Table.Tbody>
                      {(data.cycle_time_per_column ?? []).map((c) => (
                        <Table.Tr key={c.column_id}>
                          <Table.Td>
                            <Group gap={6} wrap="nowrap">
                              <Text size="xs" fw={500}>
                                {c.name}
                              </Text>
                              {c.is_done && (
                                <Badge size="xs" color="green" variant="light">
                                  done
                                </Badge>
                              )}
                            </Group>
                          </Table.Td>
                          <Table.Td>{c.stats.n}</Table.Td>
                          <Table.Td>{c.stats.n > 0 ? formatDuration(c.stats.p50_ms) : "—"}</Table.Td>
                          <Table.Td>{c.stats.n > 0 ? formatDuration(c.stats.p90_ms) : "—"}</Table.Td>
                          <Table.Td>{c.stats.n > 0 ? formatDuration(c.stats.avg_ms) : "—"}</Table.Td>
                        </Table.Tr>
                      ))}
                    </Table.Tbody>
                  </Table>
                </Paper>
              </Grid.Col>
            </Grid>
          </>
          );
        })()}
      </Stack>
    </Box>
  );
}
