import { useEffect, useMemo, useState } from "react";
import apiClient from "@/utils/apiClient";
import { Card, CardContent } from "@/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Bar,
  BarChart,
  CartesianGrid,
  ComposedChart,
  LabelList,
  Line,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import type { TooltipProps } from "recharts";
import { MessagesSquare, TrendingUp } from "lucide-react";
import { CARD_STYLES, STUDIO_COLORS } from "@/lib/dashboard/designTokens";
import {
  DashboardSectionHeader,
  DashboardStatCard,
  DashboardStatCardSkeleton,
  ChartSkeleton,
  DashboardEmptyState,
  DashboardErrorState,
  TOOLTIP_STYLES,
  MetricPill,
  QuietStat,
  QUIET_STRIP_CLASS,
} from "@/components/dashboard/shared";
import { BusinessRangeSelect } from "@/components/dashboard/shared/BusinessRangeSelect";

type PeriodPair<T> = { current: T; previous: T };

type OverviewStats = {
  newConversations: number;
  resolved: number;
  messagesReceived: number;
  repliesSent: number;
  customersHelped: number;
};

type ResponseTimeStats = {
  firstResponse: { count: number; avgSec: number | null; medianSec: number | null };
  resolution: { count: number; avgSec: number | null; medianSec: number | null };
  resolvedFirstReply: number;
};

type SatisfactionStats = {
  great: number;
  okay: number;
  bad: number;
  total: number;
  score: number | null;
};

type TimeseriesPoint = {
  date: string;
  newConversations: number;
  resolved: number;
  messages: number;
};

type AgentEntry = {
  id: number;
  name: string;
  replies: number;
  customersHelped: number;
  closed: number;
  great: number;
  okay: number;
  bad: number;
  satScore: number | null;
};

type PhoneStats = {
  total: number;
  inbound: number;
  outbound: number;
  avgDurationSec: number | null;
  voicemails: number;
};

type FrtBucket = { bucket: string; count: number };

type FreescoutReport = {
  range: { days: number; start: string; end: string; prevStart: string; prevEnd: string };
  overview: PeriodPair<OverviewStats>;
  responseTimes: PeriodPair<ResponseTimeStats>;
  satisfaction: PeriodPair<SatisfactionStats>;
  timeseries: TimeseriesPoint[];
  channels: { email: number; phone: number; chat: number; other: number };
  agents: AgentEntry[];
  frtDistribution: FrtBucket[];
  phone: PeriodPair<PhoneStats> | null;
};

type ChartSeriesKey = "newConversations" | "resolved" | "messages";

// Sorbet Studio data hues, deliberately teal-led: Operations leads with a violet
// area, so this section leads with teal bars to keep the two visually distinct.
// Triple passes the CVD/contrast validator (ΔE ≥ 27).
const chartColors: Record<ChartSeriesKey, string> = {
  newConversations: STUDIO_COLORS.teal,
  resolved: STUDIO_COLORS.violet,
  messages: STUDIO_COLORS.amber,
};

const SERIES_LABELS: Record<ChartSeriesKey, string> = {
  newConversations: "New",
  resolved: "Resolved",
  messages: "Messages",
};

const RANGE_OPTIONS = [
  { value: "7", label: "Last 7 Days" },
  { value: "30", label: "Last 30 Days" },
  { value: "90", label: "Last 90 Days" },
  { value: "180", label: "Last 180 Days" },
  { value: "365", label: "Last Year" },
];

const REFRESH_MS = 10 * 60 * 1000;

const formatNumber = (value: number) =>
  Number.isFinite(value) ? value.toLocaleString("en-US") : "0";

// Compact duration: 45s, 12m, 3.5h, 2.1d
const formatSeconds = (seconds: number | null | undefined): string => {
  if (seconds == null || !Number.isFinite(seconds)) return "—";
  if (seconds < 60) return `${Math.round(seconds)}s`;
  if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
  if (seconds < 86400) return `${(seconds / 3600).toFixed(1)}h`;
  return `${(seconds / 86400).toFixed(1)}d`;
};

const trendPct = (current: number, previous: number): number | null =>
  previous > 0 ? ((current - previous) / previous) * 100 : null;

const formatDayLabel = (date: string) =>
  new Date(`${date}T00:00:00`).toLocaleDateString("en-US", {
    month: "short",
    day: "numeric",
  });

const CustomerServiceDashboard = () => {
  const [days, setDays] = useState("30");
  const [data, setData] = useState<FreescoutReport | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [metrics, setMetrics] = useState<Record<ChartSeriesKey, boolean>>({
    newConversations: true,
    resolved: true,
    messages: false,
  });

  useEffect(() => {
    let cancelled = false;

    const fetchReport = async (isRefresh = false) => {
      if (!isRefresh) {
        setLoading(true);
        setError(null);
      }
      try {
        const response = await apiClient.get<FreescoutReport>("/api/freescout/report", {
          params: { days },
        });
        if (!cancelled) setData(response.data);
      } catch (err: unknown) {
        if (!cancelled && !isRefresh) {
          const maybe = err as { response?: { data?: { error?: string } }; message?: string };
          setError(maybe.response?.data?.error ?? maybe.message ?? "Request failed");
        }
      } finally {
        if (!cancelled && !isRefresh) setLoading(false);
      }
    };

    void fetchReport();
    const interval = setInterval(() => void fetchReport(true), REFRESH_MS);
    return () => {
      cancelled = true;
      clearInterval(interval);
    };
  }, [days]);

  const toggleMetric = (key: ChartSeriesKey) =>
    setMetrics((prev) => ({ ...prev, [key]: !prev[key] }));

  const hasActiveMetrics = Object.values(metrics).some(Boolean);

  const chartData = useMemo(
    () =>
      (data?.timeseries ?? []).map((point) => ({
        ...point,
        label: formatDayLabel(point.date),
      })),
    [data]
  );

  const cards = useMemo(() => {
    if (!data) return [];
    const { overview, responseTimes, satisfaction } = data;
    const cur = overview.current;
    const prev = overview.previous;
    const rt = responseTimes.current;
    const sat = satisfaction.current;
    const satPrev = satisfaction.previous;

    const rfrPct = rt.resolution.count > 0
      ? Math.round((rt.resolvedFirstReply * 100) / rt.resolution.count)
      : null;

    return [
      {
        key: "new",
        title: "New Conversations",
        value: formatNumber(cur.newConversations),
        subtitle: `${formatNumber(cur.messagesReceived)} messages received`,
        trend: trendPct(cur.newConversations, prev.newConversations),
        moreIsBetter: true,
        suffix: "%",
      },
      {
        key: "resolved",
        title: "Resolved",
        value: formatNumber(cur.resolved),
        subtitle: rfrPct != null ? `${rfrPct}% on first reply` : undefined,
        trend: trendPct(cur.resolved, prev.resolved),
        moreIsBetter: true,
        suffix: "%",
      },
      {
        key: "frt",
        title: "Median First Response",
        value: formatSeconds(rt.firstResponse.medianSec),
        subtitle: `avg ${formatSeconds(rt.firstResponse.avgSec)}`,
        // No trend pill: chat + workflow auto-replies produce sub-minute medians
        // that make percent deltas absurd (e.g. 2s → 5m reads as +14,850%)
        trend: null,
        moreIsBetter: false,
        suffix: "%",
      },
      {
        key: "satisfaction",
        title: "Satisfaction",
        value: sat.score != null ? `${sat.score}%` : "—",
        subtitle: sat.total > 0
          ? `${formatNumber(sat.total)} ratings · ${sat.great} great · ${sat.bad} bad`
          : "No ratings in period",
        trend:
          sat.score != null && satPrev.score != null ? sat.score - satPrev.score : null,
        moreIsBetter: true,
        suffix: " pts",
      },
    ];
  }, [data]);

  const hasData = (data?.overview.current.newConversations ?? 0) > 0
    || (data?.overview.current.messagesReceived ?? 0) > 0;

  const headerActions = !error ? (
    <BusinessRangeSelect value={days} onValueChange={setDays} options={RANGE_OPTIONS} />
  ) : null;

  return (
    <Card className={`w-full h-full ${CARD_STYLES.elevated}`}>
      <DashboardSectionHeader title="Customer Service" size="large" actions={headerActions} />

      <CardContent className="p-4 pt-3 space-y-3">
        {!error && (
          loading ? (
            <div className="grid grid-cols-2 lg:grid-cols-4 gap-2 w-full">
              {Array.from({ length: 4 }).map((_, index) => (
                <DashboardStatCardSkeleton key={index} hasSubtitle />
              ))}
            </div>
          ) : (
            cards.length > 0 && (
              <div className="grid grid-cols-2 lg:grid-cols-4 gap-2 w-full dashboard-stagger">
                {cards.map((card) => (
                  <DashboardStatCard
                    key={card.key}
                    title={card.title}
                    value={card.value}
                    subtitle={card.subtitle}
                    trend={
                      card.trend != null && Number.isFinite(card.trend)
                        ? {
                            value: card.trend,
                            moreIsBetter: card.moreIsBetter,
                            suffix: card.suffix,
                          }
                        : undefined
                    }
                  />
                ))}
              </div>
            )
          )
        )}

        {!error && !loading && (
          <div className="flex flex-wrap items-center gap-0.5">
            {(Object.keys(SERIES_LABELS) as ChartSeriesKey[]).map((key) => (
              <MetricPill
                key={key}
                active={metrics[key]}
                color={chartColors[key]}
                onClick={() => toggleMetric(key)}
              >
                {SERIES_LABELS[key]}
              </MetricPill>
            ))}
          </div>
        )}

        {loading ? (
          <div className="flex flex-col lg:flex-row gap-3">
            <div className="w-full lg:w-[55%]">
              <ChartSkeleton type="area" height="md" withCard={false} />
            </div>
            <div className="w-full lg:w-[45%]">
              <div className="h-[280px] rounded-xl border border-[#efede9] bg-[#faf9f7] animate-pulse" />
            </div>
          </div>
        ) : error ? (
          <DashboardErrorState
            error={`Failed to load customer service data: ${error}`}
            className="mx-0 my-0"
          />
        ) : !hasData ? (
          <DashboardEmptyState
            icon={MessagesSquare}
            title="No conversation data"
            description="Try selecting a different time range"
          />
        ) : (
          <>
            <div className="flex flex-col lg:flex-row gap-3">
              <div className={`h-[280px] w-full lg:w-[55%] ${CARD_STYLES.subtle} p-0 relative`}>
                {!hasActiveMetrics ? (
                  <DashboardEmptyState
                    icon={TrendingUp}
                    title="No metrics selected"
                    description="Select at least one metric to visualize."
                  />
                ) : (
                  <ResponsiveContainer width="100%" height="100%">
                    <ComposedChart
                      data={chartData}
                      margin={{ top: 8, right: 0, left: -8, bottom: 0 }}
                    >
                      <CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
                      <XAxis
                        dataKey="label"
                        className="text-xs text-muted-foreground"
                        tick={{ fill: "currentColor" }}
                        minTickGap={24}
                      />
                      <YAxis
                        tickFormatter={(value: number) => formatNumber(value)}
                        className="text-xs text-muted-foreground"
                        tick={{ fill: "currentColor" }}
                        allowDecimals={false}
                      />
                      <Tooltip content={<ConversationsTooltip />} />
                      {metrics.newConversations && (
                        <Bar
                          dataKey="newConversations"
                          name={SERIES_LABELS.newConversations}
                          fill={chartColors.newConversations}
                          fillOpacity={0.75}
                          radius={[6, 6, 0, 0]}
                          maxBarSize={18}
                        />
                      )}
                      {metrics.resolved && (
                        <Line
                          type="monotone"
                          dataKey="resolved"
                          name={SERIES_LABELS.resolved}
                          stroke={chartColors.resolved}
                          strokeWidth={2}
                          dot={false}
                          activeDot={{ r: 4 }}
                        />
                      )}
                      {metrics.messages && (
                        <Line
                          type="monotone"
                          dataKey="messages"
                          name={SERIES_LABELS.messages}
                          stroke={chartColors.messages}
                          strokeWidth={2}
                          strokeDasharray="5 3"
                          dot={false}
                          activeDot={{ r: 4 }}
                        />
                      )}
                    </ComposedChart>
                  </ResponsiveContainer>
                )}
              </div>
              <div className="w-full lg:w-[45%]">
                <AgentLeaderboard agents={data?.agents ?? []} />
              </div>
            </div>

            <FrtHistogram
              buckets={data?.frtDistribution ?? []}
              medianSec={data?.responseTimes.current.firstResponse.medianSec ?? null}
            />

            <SecondaryStats data={data!} />
          </>
        )}
      </CardContent>
    </Card>
  );
};

const ConversationsTooltip = ({ active, payload, label }: TooltipProps<number, string>) => {
  if (!active || !payload?.length) return null;

  return (
    <div className={TOOLTIP_STYLES.container}>
      <p className={TOOLTIP_STYLES.header}>{label}</p>
      <div className={TOOLTIP_STYLES.content}>
        {payload.map((entry, index) => (
          <div key={index} className={TOOLTIP_STYLES.row}>
            <div className={TOOLTIP_STYLES.rowLabel}>
              <span
                className={TOOLTIP_STYLES.dot}
                style={{ backgroundColor: entry.stroke || entry.color || "#888" }}
              />
              <span className={TOOLTIP_STYLES.name}>{entry.name}</span>
            </div>
            <span className={TOOLTIP_STYLES.value}>
              {entry.value != null ? formatNumber(entry.value as number) : "—"}
            </span>
          </div>
        ))}
      </div>
    </div>
  );
};

// How-fast-do-we-answer histogram over FreeScout's report buckets. Single-series,
// so no legend; direct count labels on the bars carry the values.
function FrtHistogram({
  buckets,
  medianSec,
}: {
  buckets: FrtBucket[];
  medianSec: number | null;
}) {
  const total = buckets.reduce((sum, b) => sum + b.count, 0);
  if (total === 0) return null;

  return (
    <div className={`${CARD_STYLES.subtle} px-3 pb-1 pt-2.5`}>
      <div className="flex items-baseline justify-between px-1">
        <span className="text-[10.5px] font-semibold uppercase tracking-wide text-[#a09b92]">
          First Response Time
        </span>
        <span className="text-[10.5px] text-[#7c7870]">
          median {formatSeconds(medianSec)} · {formatNumber(total)} conversations
        </span>
      </div>
      <div className="h-[120px]">
        <ResponsiveContainer width="100%" height="100%">
          <BarChart data={buckets} margin={{ top: 18, right: 4, left: 4, bottom: 0 }}>
            <XAxis
              dataKey="bucket"
              interval={0}
              tickLine={false}
              axisLine={false}
              tick={{ fill: "#7c7870", fontSize: 10 }}
            />
            <YAxis hide />
            <Bar
              dataKey="count"
              fill={STUDIO_COLORS.violet}
              fillOpacity={0.8}
              radius={[6, 6, 0, 0]}
              maxBarSize={44}
              minPointSize={3}
            >
              <LabelList
                dataKey="count"
                position="top"
                formatter={(value: number) => (value > 0 ? formatNumber(value) : "")}
                style={{ fill: "#7c7870", fontSize: 10 }}
              />
            </Bar>
          </BarChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}

const TABLE_HEAD_CLASS =
  "h-8 px-2 text-[10.5px] font-semibold uppercase tracking-wide text-[#a09b92]";

function AgentLeaderboard({ agents }: { agents: AgentEntry[] }) {
  if (agents.length === 0) {
    return (
      <div className="h-[280px] rounded-xl border border-[#efede9] bg-[#faf9f7] flex items-center justify-center">
        <p className="text-sm text-muted-foreground">No agent activity</p>
      </div>
    );
  }

  return (
    <div className="h-[280px] rounded-xl border border-[#efede9] bg-[#faf9f7] overflow-hidden flex flex-col">
      <div className="flex-1 overflow-auto">
        <Table>
          <TableHeader className="sticky top-0 z-10 bg-[#faf9f7]">
            <TableRow className="hover:bg-transparent">
              <TableHead className={`${TABLE_HEAD_CLASS} w-8`} />
              <TableHead className={TABLE_HEAD_CLASS}>Agent</TableHead>
              <TableHead className={`${TABLE_HEAD_CLASS} text-right`}>Replies</TableHead>
              <TableHead className={`${TABLE_HEAD_CLASS} text-right`}>Closed</TableHead>
              <TableHead className={`${TABLE_HEAD_CLASS} text-right`}>Helped</TableHead>
              <TableHead className={`${TABLE_HEAD_CLASS} text-right`}>CSAT</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {agents.map((agent, index) => (
              <TableRow key={agent.id}>
                <TableCell className="py-1.5 px-2 w-8 text-xs text-muted-foreground text-center">
                  {index + 1}
                </TableCell>
                <TableCell className="py-1.5 px-2 text-xs font-medium truncate max-w-[110px]">
                  {agent.name}
                </TableCell>
                <TableCell className="py-1.5 px-2 text-xs text-right font-medium">
                  {formatNumber(agent.replies)}
                </TableCell>
                <TableCell className="py-1.5 px-2 text-xs text-right text-muted-foreground">
                  {agent.closed > 0 ? formatNumber(agent.closed) : "—"}
                </TableCell>
                <TableCell className="py-1.5 px-2 text-xs text-right text-muted-foreground">
                  {agent.customersHelped > 0 ? formatNumber(agent.customersHelped) : "—"}
                </TableCell>
                <TableCell className="py-1.5 px-2 text-xs text-right">
                  {agent.satScore != null ? (
                    <span
                      className={
                        agent.satScore >= 80
                          ? "text-emerald-600 font-medium"
                          : agent.satScore >= 50
                            ? "text-amber-600 font-medium"
                            : "text-red-600 font-medium"
                      }
                    >
                      {agent.satScore}%
                    </span>
                  ) : (
                    <span className="text-muted-foreground">—</span>
                  )}
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
    </div>
  );
}

function SecondaryStats({ data }: { data: FreescoutReport }) {
  const { overview, responseTimes, channels, phone, range } = data;
  const cur = overview.current;
  const totalChannels = channels.email + channels.chat + channels.phone + channels.other;
  const pct = (n: number) =>
    totalChannels > 0 ? `${Math.round((n * 100) / totalChannels)}%` : "0%";

  const phoneCur = phone?.current ?? null;
  const phonePrev = phone?.previous ?? null;

  return (
    <div className="space-y-2">
      <div className={`${QUIET_STRIP_CLASS} grid-cols-2 sm:grid-cols-3 lg:grid-cols-6`}>
        <QuietStat label="Replies Sent" value={formatNumber(cur.repliesSent)} />
        <QuietStat label="Customers Helped" value={formatNumber(cur.customersHelped)} />
        <QuietStat
          label="Median Resolution"
          value={formatSeconds(responseTimes.current.resolution.medianSec)}
          sub={`avg ${formatSeconds(responseTimes.current.resolution.avgSec)}`}
        />
        <QuietStat label="Email" value={formatNumber(channels.email)} sub={pct(channels.email)} />
        <QuietStat label="Chat" value={formatNumber(channels.chat)} sub={pct(channels.chat)} />
        <QuietStat label="Phone" value={formatNumber(channels.phone)} sub={pct(channels.phone)} />
      </div>

      {phoneCur && (
        <div className={`${QUIET_STRIP_CLASS} grid-cols-2 sm:grid-cols-4`}>
          <QuietStat
            label="Calls"
            value={formatNumber(phoneCur.total)}
            sub={`${formatNumber(phoneCur.inbound)} in · ${formatNumber(phoneCur.outbound)} out`}
          />
          <QuietStat
            label="Calls / Day"
            value={(phoneCur.total / range.days).toFixed(1)}
            sub={phonePrev ? `${(phonePrev.total / range.days).toFixed(1)} prior period` : undefined}
          />
          <QuietStat label="Avg Call" value={formatSeconds(phoneCur.avgDurationSec)} />
          <QuietStat label="Voicemails" value={formatNumber(phoneCur.voicemails)} />
        </div>
      )}
    </div>
  );
}

export default CustomerServiceDashboard;
