import { Head, router } from "@inertiajs/react";
import { useEffect, useMemo, useRef, useState } from "react";
import * as L from "leaflet";
import "leaflet/dist/leaflet.css";
import {
    Bar,
    BarChart,
    CartesianGrid,
    ResponsiveContainer,
    Tooltip,
    XAxis,
} from "recharts";
import {
    AlertTriangle,
    CalendarDays,
    MapPin,
    Package,
    Receipt,
    ShoppingCart,
    Sparkles,
    TrendingUp,
    Users,
    Wallet,
} from "lucide-react";

import AppLayout from "@/layouts/app-layout";

import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { StatChip } from "@/components/crm/global-card";

type Day = {
    date: string;
    label: string;
    sales: number;
    payments: number;
};

type Summary = {
    sales: number;
    orders: number;
    payments: number;
    new_customers: number;
    new_products: number;
    outstanding: number;
    overdue: number;
};

type Product = {
    id?: string | number;
    name: string;
    qty: number;
    revenue: number;
};

type SalesPerson = {
    id?: string | number;
    name: string;
    orders: number;
    revenue: number;
};

type MapPoint = {
    id: string;
    lat: number;
    lng: number;
    title: string;
    description?: string;
    type: "customer" | "visit" | "order";
};

const money = (value: number) =>
    new Intl.NumberFormat("id-ID", {
        style: "currency",
        currency: "IDR",
        maximumFractionDigits: 0,
    }).format(value || 0);

const moneyCompact = (value: number) =>
    new Intl.NumberFormat("id-ID", {
        style: "currency",
        currency: "IDR",
        notation: "compact",
        maximumFractionDigits: 1,
    }).format(value || 0);

const number = (value: number) => value.toLocaleString("id-ID");

const initials = (name: string) =>
    name
        .split(" ")
        .filter(Boolean)
        .slice(0, 2)
        .map((part) => part[0]?.toUpperCase())
        .join("");

const monthLabel = (value: string) => {
    const [year, monthNumber] = value.split("-").map(Number);
    if (!year || !monthNumber) return value;
    return new Intl.DateTimeFormat("id-ID", {
        month: "long",
        year: "numeric",
    }).format(new Date(year, monthNumber - 1, 1));
};

function escapeHtml(value: string) {
    return value
        .replaceAll("&", "&amp;")
        .replaceAll("<", "&lt;")
        .replaceAll(">", "&gt;")
        .replaceAll('"', "&quot;")
        .replaceAll("'", "&#039;");
}

const CHART_COLORS = {
    sales: "#93c5fd",
    payments: "#2563eb",
};

const CHART_LABELS: Record<string, string> = {
    sales: "Penjualan",
    payments: "Pembayaran",
};

function DailyChartTooltip({
    active,
    payload,
    label,
}: {
    active?: boolean;
    payload?: Array<{ dataKey: string; value: number; color: string }>;
    label?: string;
}) {
    if (!active || !payload?.length) {
        return null;
    }

    return (
        <div className="min-w-50 rounded-xl border border-slate-100 bg-card px-3.5 py-3 text-sm shadow-lg shadow-slate-900/10">
            <div className="mb-2 text-xs font-bold uppercase tracking-wide text-muted-foreground/80">{`Tanggal ${label}`}</div>

            <div className="space-y-1.5">
                {[...payload].reverse().map((item) => (
                    <div
                        key={item.dataKey}
                        className="flex w-full items-center gap-2"
                    >
                        <span
                            className="h-3.5 w-1 shrink-0 rounded-sm"
                            style={{ backgroundColor: item.color }}
                        />

                        <span className="flex-1 text-muted-foreground">
                            {CHART_LABELS[item.dataKey] ?? item.dataKey}
                        </span>

                        <span className="font-mono font-semibold tabular-nums text-foreground">
                            {money(Number(item.value))}
                        </span>
                    </div>
                ))}
            </div>
        </div>
    );
}

function RankedRow({
    rank,
    badge,
    title,
    value,
    meta,
    progress,
}: {
    rank?: number;
    badge?: React.ReactNode;
    title: string;
    value: string;
    meta: string;
    progress: number;
}) {
    return (
        <div className="flex items-start gap-3">
            {badge ?? (
                <span className="mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-full bg-blue-50 text-xs font-bold text-blue-600">
                    {rank}
                </span>
            )}

            <div className="min-w-0 flex-1">
                <div className="mb-1.5 flex items-center justify-between gap-2 text-sm">
                    <span className="truncate font-semibold text-foreground">
                        {title}
                    </span>

                    <span className="shrink-0 tabular-nums font-semibold text-foreground/80">
                        {value}
                    </span>
                </div>

                <div className="h-1.5 overflow-hidden rounded-full bg-muted">
                    <div
                        className="h-1.5 rounded-full bg-linear-to-r from-blue-400 to-blue-600 transition-all"
                        style={{
                            width: `${Math.min(Math.max(progress, 0), 100)}%`,
                        }}
                    />
                </div>

                <div className="mt-1 text-xs text-muted-foreground/80">{meta}</div>
            </div>
        </div>
    );
}

const MAP_TYPE_META: Record<
    MapPoint["type"],
    { color: string; label: string }
> = {
    customer: { color: "#2563eb", label: "Customer" },
    visit: { color: "#10b981", label: "Kunjungan Sales" },
    order: { color: "#8b5cf6", label: "Order" },
};

function DistributionMap({
    points,
    truncated = false,
}: {
    points: MapPoint[];
    truncated?: boolean;
}) {
    const mapRef = useRef<HTMLDivElement | null>(null);
    const mapInstanceRef = useRef<L.Map | null>(null);
    const layerRef = useRef<L.LayerGroup | null>(null);

    useEffect(() => {
        if (!mapRef.current) return;

        const fallback = { lat: -6.2, lng: 106.816666 };
        const validPoints = points.filter(
            (point) =>
                Number.isFinite(Number(point.lat)) &&
                Number.isFinite(Number(point.lng)),
        );
        const center = validPoints[0] ?? fallback;

        if (!mapInstanceRef.current) {
            mapInstanceRef.current = L.map(mapRef.current, {
                center: [Number(center.lat), Number(center.lng)],
                zoom: 12,
                zoomControl: true,
                attributionControl: true,
                scrollWheelZoom: false,
                doubleClickZoom: true,
                dragging: true,
            });

            L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
                maxZoom: 19,
                attribution: "&copy; OpenStreetMap contributors",
            }).addTo(mapInstanceRef.current);

            layerRef.current = L.layerGroup().addTo(mapInstanceRef.current);
        }

        const map = mapInstanceRef.current;
        const layer = layerRef.current;
        if (!map || !layer) return;

        layer.clearLayers();

        const bounds: L.LatLngExpression[] = [];

        validPoints.forEach((point) => {
            const meta = MAP_TYPE_META[point.type] ?? MAP_TYPE_META.customer;
            const latLng: L.LatLngExpression = [
                Number(point.lat),
                Number(point.lng),
            ];
            bounds.push(latLng);

            const marker = L.circleMarker(latLng, {
                radius: point.type === "visit" ? 7 : 6,
                color: "#ffffff",
                weight: 3,
                fillColor: meta.color,
                fillOpacity: 0.95,
            }).addTo(layer);

            marker.bindPopup(`
                <div style="min-width:170px;font-family:Inter,system-ui,sans-serif">
                    <div style="font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:${meta.color};margin-bottom:4px">${escapeHtml(meta.label)}</div>
                    <div style="font-size:13px;font-weight:700;color:#0f172a;margin-bottom:2px">${escapeHtml(point.title || "-")}</div>
                    <div style="font-size:11px;color:#64748b">${escapeHtml(point.description || "")}</div>
                </div>
            `);
        });

        if (bounds.length > 1) {
            map.fitBounds(L.latLngBounds(bounds), {
                padding: [28, 28],
                maxZoom: 14,
            });
        } else if (bounds.length === 1) {
            map.setView(bounds[0], 14, { animate: false });
        } else {
            map.setView([fallback.lat, fallback.lng], 5, { animate: false });
        }

        const timer = window.setTimeout(() => {
            if (mapInstanceRef.current) {
                mapInstanceRef.current.invalidateSize();
            }
        }, 50);

        return () => {
            window.clearTimeout(timer);
        };
    }, [points]);

    useEffect(() => {
        return () => {
            mapInstanceRef.current?.remove();
            mapInstanceRef.current = null;
            layerRef.current = null;
        };
    }, []);

    return (
        <div className="relative h-90 overflow-hidden rounded-xl border border-slate-100 bg-muted">
            <div ref={mapRef} className="h-full w-full" />

            <div className="pointer-events-none absolute left-3 top-3 rounded-lg border border-white/80 bg-card/95 px-3 py-2 text-[11px] font-semibold text-muted-foreground shadow-sm backdrop-blur">
                {points.length
                    ? `${points.length}${truncated ? "+" : ""} titik aktivitas pada periode ini`
                    : "Belum ada titik pada periode ini"}
            </div>

            {!points.length && (
                <div className="absolute inset-0 flex items-center justify-center bg-card/60 text-sm text-muted-foreground/80">
                    Belum ada data lokasi untuk ditampilkan.
                </div>
            )}
        </div>
    );
}

export default function AnalyticsPage({
    month,
    summary,
    days,
    topProducts,
    salesPerformance,
    mapPoints = [],
    mapPointsTruncated = false,
}: {
    month: string;
    summary: Summary;
    days: Day[];
    topProducts: Product[];
    salesPerformance: SalesPerson[];
    mapPoints?: MapPoint[];
    mapPointsTruncated?: boolean;
}) {
    const [selectedMonth, setSelectedMonth] = useState(month);

    useEffect(() => {
        setSelectedMonth(month);
    }, [month]);

    const handleMonthChange = (newMonth: string) => {
        setSelectedMonth(newMonth);
        if (newMonth && newMonth !== month) {
            router.get(
                "/crm/analytics",
                { month: newMonth },
                { preserveState: true, preserveScroll: true },
            );
        }
    };

    const maxProduct = useMemo(
        () =>
            Math.max(
                ...topProducts.map((product) => Number(product.revenue)),
                1,
            ),
        [topProducts],
    );

    const maxSales = useMemo(
        () =>
            Math.max(
                ...salesPerformance.map((sales) => Number(sales.revenue)),
                1,
            ),
        [salesPerformance],
    );

    const avgOrderValue =
        summary.orders > 0 ? summary.sales / summary.orders : 0;

    const paymentToSalesRatio =
        summary.sales > 0 ? (summary.payments / summary.sales) * 100 : 0;

    return (
        <AppLayout
            breadcrumbs={[
                {
                    title: "Analytics",
                    href: "/crm/analytics",
                },
            ]}
        >
            <Head title="Analytics" />

            <div className="crm-page space-y-6 pb-10">
                {/* Header */}
                <section className="flex flex-col gap-5 lg:flex-row lg:items-end lg:justify-between">
                    <div>
                        <p className="flex items-center gap-1.5 text-sm font-medium text-blue-600">
                            <Sparkles className="size-3.5" />
                            Analytics
                        </p>
                        <h1 className="mt-1 text-2xl font-bold tracking-tight text-foreground md:text-[28px]">
                            Sales Analytics
                        </h1>
                        <p className="mt-1 text-sm text-muted-foreground">
                            Ringkasan performa bisnis untuk{" "}
                            <span className="font-semibold text-foreground/80">
                                {monthLabel(month)}
                            </span>
                            .
                        </p>
                    </div>

                    <div className="flex items-center gap-2">
                        <div className="flex h-11 items-center gap-2 rounded-xl border border-border bg-card px-3.5 shadow-sm transition focus-within:border-blue-300 focus-within:ring-2 focus-within:ring-blue-500/15">
                            <CalendarDays className="size-4 shrink-0 text-muted-foreground/80" />
                            <label
                                htmlFor="select-month-input"
                                className="sr-only"
                            >
                                Pilih Bulan
                            </label>
                            <Input
                                id="select-month-input"
                                type="month"
                                value={selectedMonth}
                                onChange={(event) =>
                                    handleMonthChange(event.target.value)
                                }
                                className="h-9 w-36 border-0 bg-transparent px-0 text-sm font-medium text-foreground/80 shadow-none focus-visible:ring-0"
                            />
                        </div>
                    </div>
                </section>

                {/* Primary metrics */}
                <section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
                    <StatChip
                        icon={TrendingUp}
                        label="Penjualan"
                        value={money(summary.sales)}
                        tone="blue"
                        variant="compact"
                        description={`Rata-rata order ${moneyCompact(avgOrderValue)}`}
                    />

                    <StatChip
                        icon={ShoppingCart}
                        label="Order"
                        value={number(summary.orders)}
                        tone="violet"
                        variant="compact"
                        description="Order terealisasi bulan ini"
                    />

                    <StatChip
                        icon={Wallet}
                        label="Pembayaran"
                        value={money(summary.payments)}
                        tone="emerald"
                        variant="compact"
                        description={`${paymentToSalesRatio.toFixed(0)}% dibanding penjualan bulan ini`}
                    />

                    <StatChip
                        icon={Receipt}
                        label="Piutang"
                        value={money(summary.outstanding)}
                        tone="orange"
                        variant="compact"
                        description="Piutang belum lunas saat ini"
                    />
                </section>

                {/* Secondary metrics */}
                <section className="grid gap-4 sm:grid-cols-3">
                    <StatChip
                        icon={Users}
                        label="Customer Baru"
                        value={number(summary.new_customers)}
                        tone="cyan"
                        variant="compact"
                        description="Bergabung bulan ini"
                    />

                    <StatChip
                        icon={Package}
                        label="Produk Baru"
                        value={number(summary.new_products)}
                        tone="cyan"
                        variant="compact"
                        description="Ditambahkan bulan ini"
                    />

                    <StatChip
                        icon={AlertTriangle}
                        label="Jatuh Tempo"
                        value={money(summary.overdue)}
                        tone="rose"
                        variant="compact"
                        description="Piutang overdue saat ini"
                    />
                </section>

                {/* Daily Sales Chart */}
                <Card className="overflow-hidden border-border/80 bg-card shadow-sm">
                    <CardHeader className="flex flex-row items-center justify-between px-5 pb-0 pt-0">
                        <div>
                            <CardTitle className="text-[15px] font-bold text-foreground">
                                Penjualan & Pembayaran Harian
                            </CardTitle>
                            <p className="mt-1 text-xs text-muted-foreground/80">
                                Tren transaksi harian sepanjang{" "}
                                {monthLabel(month)}.
                            </p>
                        </div>
                        <span className="shrink-0 rounded-full border border-blue-100 bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-700">
                            {monthLabel(month)}
                        </span>
                    </CardHeader>

                    <CardContent className="px-5 pb-5">
                        <div className="h-72 w-full min-w-0 overflow-hidden">
                            <ResponsiveContainer width="100%" height="100%">
                                <BarChart
                                    width={1000}
                                    height={288}
                                    data={days}
                                    margin={{
                                        top: 8,
                                        right: 8,
                                        left: 8,
                                        bottom: 8,
                                    }}
                                >
                                    <CartesianGrid
                                        vertical={false}
                                        strokeDasharray="3 3"
                                    />

                                    <XAxis
                                        dataKey="label"
                                        tickLine={false}
                                        axisLine={false}
                                        tickMargin={8}
                                        tick={{ fontSize: 11, fill: "#94a3b8" }}
                                    />

                                    <Tooltip
                                        cursor={{
                                            fill: "rgba(37, 99, 235, 0.08)",
                                        }}
                                        content={<DailyChartTooltip />}
                                    />
                                    <Bar
                                        dataKey="sales"
                                        name="Penjualan"
                                        stackId="daily"
                                        fill={CHART_COLORS.sales}
                                        radius={[0, 0, 0, 0]}
                                    />

                                    <Bar
                                        dataKey="payments"
                                        name="Pembayaran"
                                        stackId="daily"
                                        fill={CHART_COLORS.payments}
                                        radius={[4, 4, 0, 0]}
                                    />
                                </BarChart>
                            </ResponsiveContainer>
                        </div>

                        <div className="mt-3 flex items-center gap-4 text-xs text-muted-foreground">
                            <span className="flex items-center gap-1.5">
                                <span
                                    className="h-2.5 w-2.5 rounded-sm"
                                    style={{
                                        backgroundColor: CHART_COLORS.sales,
                                    }}
                                />
                                Penjualan
                            </span>

                            <span className="flex items-center gap-1.5">
                                <span
                                    className="h-2.5 w-2.5 rounded-sm"
                                    style={{
                                        backgroundColor: CHART_COLORS.payments,
                                    }}
                                />
                                Pembayaran
                            </span>
                        </div>
                    </CardContent>
                </Card>

                {/* Products & Sales */}
                <section className="grid gap-5 xl:grid-cols-2">
                    {/* Top Products */}
                    <Card className="border-border/80 bg-card shadow-sm">
                        <CardHeader className="px-5 pb-0 pt-0">
                            <CardTitle className="text-[15px] font-bold text-foreground">
                                Produk Terlaris
                            </CardTitle>
                            <p className="mt-1 text-xs text-muted-foreground/80">
                                5 produk dengan revenue tertinggi bulan ini.
                            </p>
                        </CardHeader>

                        <CardContent className="space-y-5 px-5 pb-5 pt-4">
                            {topProducts.length ? (
                                topProducts.map((product, index) => (
                                    <RankedRow
                                        key={
                                            product.id ??
                                            `${product.name}-${index}`
                                        }
                                        rank={index + 1}
                                        title={product.name}
                                        value={money(Number(product.revenue))}
                                        meta={`${number(Number(product.qty))} unit terjual`}
                                        progress={
                                            (Number(product.revenue) /
                                                maxProduct) *
                                            100
                                        }
                                    />
                                ))
                            ) : (
                                <div className="py-10 text-center text-sm text-muted-foreground/80">
                                    Belum ada penjualan pada periode ini.
                                </div>
                            )}
                        </CardContent>
                    </Card>

                    {/* Sales Performance */}
                    <Card className="border-border/80 bg-card shadow-sm">
                        <CardHeader className="px-5 pb-0 pt-0">
                            <CardTitle className="text-[15px] font-bold text-foreground">
                                Performa Sales
                            </CardTitle>
                            <p className="mt-1 text-xs text-muted-foreground/80">
                                Ranking revenue tim sales bulan ini.
                            </p>
                        </CardHeader>

                        <CardContent className="space-y-5 px-5 pb-5 pt-4">
                            {salesPerformance.length ? (
                                salesPerformance.map((sales, index) => (
                                    <RankedRow
                                        key={
                                            sales.id ?? `${sales.name}-${index}`
                                        }
                                        badge={
                                            <span className="mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-full bg-violet-50 text-[10px] font-bold text-violet-600">
                                                {initials(sales.name)}
                                            </span>
                                        }
                                        title={sales.name}
                                        value={money(Number(sales.revenue))}
                                        meta={`${number(Number(sales.orders))} order`}
                                        progress={
                                            (Number(sales.revenue) / maxSales) *
                                            100
                                        }
                                    />
                                ))
                            ) : (
                                <div className="py-10 text-center text-sm text-muted-foreground/80">
                                    Belum ada data sales pada periode ini.
                                </div>
                            )}
                        </CardContent>
                    </Card>
                </section>

                {/* Distribution map */}
                <Card className="relative z-0 overflow-hidden border-border/80 bg-card shadow-sm">
                    <CardHeader className="flex flex-row items-center justify-between px-5 pb-0 pt-0">
                        <div>
                            <CardTitle className="flex items-center gap-2 text-[15px] font-bold text-foreground">
                                <MapPin className="size-4 text-blue-500" />
                                Peta Sebaran Customer & Aktivitas
                            </CardTitle>
                            <p className="mt-1 text-xs text-muted-foreground/80">
                                Customer yang memiliki aktivitas, kunjungan, dan
                                order pada {monthLabel(month)}.
                            </p>
                        </div>
                    </CardHeader>

                    <CardContent className="px-5">
                        <DistributionMap
                            points={mapPoints}
                            truncated={mapPointsTruncated}
                        />

                        <div className="mt-3 flex flex-wrap items-center gap-5 px-1 text-[11px] text-muted-foreground">
                            {(
                                Object.keys(MAP_TYPE_META) as MapPoint["type"][]
                            ).map((type) => (
                                <span
                                    key={type}
                                    className="flex items-center gap-1.5"
                                >
                                    <span
                                        className="size-2.5 rounded-full"
                                        style={{
                                            backgroundColor:
                                                MAP_TYPE_META[type].color,
                                        }}
                                    />
                                    {MAP_TYPE_META[type].label}
                                </span>
                            ))}
                        </div>
                    </CardContent>
                </Card>

                <footer className="flex items-center justify-between border-t border-border/80 pt-4 text-[11px] text-muted-foreground/80">
                    <span>
                        © {new Date().getFullYear()} MINANGA. All rights
                        reserved.
                    </span>
                    <span>Analytics v1.0</span>
                </footer>
            </div>
        </AppLayout>
    );
}
