import { useMemo, useState, ReactNode } from "react";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Progress } from "@/components/ui/progress";
import { cn } from "@/lib/utils";
import { PoundSterling, TrendingUp, BarChart3, Calendar as CalendarIcon, ArrowUp, ArrowDown } from "lucide-react";
import {
  differenceInCalendarDays,
  eachMonthOfInterval,
  endOfDay,
  format,
  isWithinInterval,
  startOfDay,
  startOfMonth,
  subDays,
  subMonths,
} from "date-fns";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Area, AreaChart } from "recharts";
import AdminLayout from "@/layouts/AdminLayout";
import { grossCents } from "@/lib/vat";

const fmtGBP = (cents: number) => `£${(cents / 100).toLocaleString("en-GB", { minimumFractionDigits: 2 })}`;
// Revenue figures shown to staff are gross (incl-VAT) — matches what the
// customer actually paid us, and keeps /admin/revenue consistent with the
// Orders / Dashboard / CompanyPortal stats. DB still stores ex-VAT.
const netRevenueCents = (o: { price_cents: number; refund_cents: number }) =>
  grossCents(o.price_cents) - grossCents(o.refund_cents || 0);

// When the order was placed. created_at arrives from the admin API as a UTC
// "yyyy-mm-dd hh:mm:ss" string; parse as UTC so days/months bucket in the
// viewer's timezone (same convention as Admin/Dashboard).
const orderPlacedAt = (o: { created_at?: string | null }) =>
  new Date(String(o.created_at || "").replace(" ", "T") + "Z");

const presetRanges = [
  { label: "Last 7 days", days: 7 },
  { label: "Last 30 days", days: 30 },
  { label: "Last 90 days", days: 90 },
  { label: "This month", days: -1 },
];

const RevenueAnalyticsPage = () => {
  const [dateRange, setDateRange] = useState<{ from: Date; to: Date }>({
    from: subDays(new Date(), 30),
    to: new Date(),
  });

  const applyPreset = (days: number) => {
    if (days === -1) {
      setDateRange({ from: startOfMonth(new Date()), to: new Date() });
    } else {
      setDateRange({ from: subDays(new Date(), days), to: new Date() });
    }
  };

  const { data: orders } = useQuery({
    queryKey: ["revenue-orders"],
    queryFn: async (): Promise<any[]> => {
      const res = await fetch("/api/admin/revenue/orders");
      if (!res.ok) return [];
      return res.json();
    },
  });

  const analytics = useMemo(() => {
    if (!orders) return null;

    const now = new Date();
    const rangeStart = startOfDay(dateRange.from);
    const rangeEnd = endOfDay(dateRange.to);
    const rangeDays = Math.max(1, differenceInCalendarDays(dateRange.to, dateRange.from) + 1);
    const prevEnd = endOfDay(subDays(dateRange.from, 1));
    const prevStart = startOfDay(subDays(dateRange.from, rangeDays));

    const recentOrders = orders.filter((o) =>
      isWithinInterval(orderPlacedAt(o), { start: rangeStart, end: rangeEnd })
    );
    const previousOrders = orders.filter((o) =>
      isWithinInterval(orderPlacedAt(o), { start: prevStart, end: prevEnd })
    );

    // Real course_orders statuses are paid/confirmed/complete ('complete' is
    // what the admin mark-complete action writes); 'completed' kept defensively.
    const paidStatuses = ["paid", "confirmed", "complete", "completed"];
    const currentRevenue = recentOrders.filter((o) => paidStatuses.includes(o.status)).reduce((s, o) => s + netRevenueCents(o), 0);
    const previousRevenue = previousOrders.filter((o) => paidStatuses.includes(o.status)).reduce((s, o) => s + netRevenueCents(o), 0);
    const revenueChange = previousRevenue > 0 ? ((currentRevenue - previousRevenue) / previousRevenue) * 100 : 0;

    const currentBookings = recentOrders.filter((o) => paidStatuses.includes(o.status)).length;
    const previousBookings = previousOrders.filter((o) => paidStatuses.includes(o.status)).length;
    const bookingChange = previousBookings > 0 ? ((currentBookings - previousBookings) / previousBookings) * 100 : 0;

    const avgOrderValue = currentBookings > 0 ? currentRevenue / currentBookings : 0;
    const prevAvgOrder = previousBookings > 0 ? previousRevenue / previousBookings : 0;
    const aovChange = prevAvgOrder > 0 ? ((avgOrderValue - prevAvgOrder) / prevAvgOrder) * 100 : 0;

    // Monthly revenue for chart — 12-month historical trend, independent of filter
    const monthlyData = eachMonthOfInterval({
      start: subMonths(now, 11),
      end: now,
    }).map((month) => {
      const monthOrders = orders.filter((o) => {
        const d = orderPlacedAt(o);
        return d.getMonth() === month.getMonth() && d.getFullYear() === month.getFullYear() && paidStatuses.includes(o.status);
      });
      return {
        month: format(month, "MMM yy"),
        revenue: monthOrders.reduce((s, o) => s + (netRevenueCents(o)), 0) / 100,
        bookings: monthOrders.length,
      };
    });

    const paidInRange = recentOrders.filter((o) => paidStatuses.includes(o.status));

    // Revenue by category (filtered to selected range)
    const categoryMap = new Map<string, number>();
    paidInRange.forEach((o) => {
      const cat = (o.course as any)?.category || "Unknown";
      categoryMap.set(cat, (categoryMap.get(cat) || 0) + netRevenueCents(o));
    });
    const byCategory = Array.from(categoryMap.entries())
      .map(([name, cents]) => ({ name, revenue: cents / 100 }))
      .sort((a, b) => b.revenue - a.revenue);

    // Revenue by payment method (filtered to selected range)
    const methodMap = new Map<string, number>();
    paidInRange.forEach((o) => {
      const method = o.payment_method || "stripe";
      methodMap.set(method, (methodMap.get(method) || 0) + netRevenueCents(o));
    });
    const byMethod = Array.from(methodMap.entries()).map(([name, cents]) => ({ name, revenue: cents / 100 }));

    // Top courses (filtered to selected range)
    const courseMap = new Map<string, { revenue: number; bookings: number }>();
    paidInRange.forEach((o) => {
      const title = (o.course as any)?.title || "Unknown";
      const existing = courseMap.get(title) || { revenue: 0, bookings: 0 };
      courseMap.set(title, {
        revenue: existing.revenue + netRevenueCents(o),
        bookings: existing.bookings + 1,
      });
    });
    const topCourses = Array.from(courseMap.entries())
      .map(([title, data]) => ({ title, ...data }))
      .sort((a, b) => b.revenue - a.revenue)
      .slice(0, 10);

    // Simple forecast: avg last 3 months projected forward
    const last3 = monthlyData.slice(-3);
    const avgMonthly = last3.reduce((s, m) => s + m.revenue, 0) / 3;
    const forecastMonths = [1, 2, 3].map((i) => ({
      month: format(subMonths(now, -i), "MMM yy"),
      revenue: Math.round(avgMonthly * (1 + 0.02 * i)),
      forecast: true,
    }));

    return {
      rangeDays,
      currentRevenue, previousRevenue, revenueChange,
      currentBookings, previousBookings, bookingChange,
      avgOrderValue, aovChange,
      monthlyData, forecastMonths,
      byCategory, byMethod, topCourses,
      totalRevenue: orders.filter((o) => paidStatuses.includes(o.status)).reduce((s, o) => s + netRevenueCents(o), 0),
    };
  }, [orders, dateRange]);

  if (!analytics) {
    return <div className="text-muted-foreground">Loading revenue analytics...</div>;
  }

  const ChangeIndicator = ({ value }: { value: number }) => (
    <span className={`inline-flex items-center text-xs font-medium ${value >= 0 ? "text-green-600" : "text-destructive"}`}>
      {value >= 0 ? <ArrowUp className="h-3 w-3 mr-0.5" /> : <ArrowDown className="h-3 w-3 mr-0.5" />}
      {Math.abs(value).toFixed(1)}%
    </span>
  );

  const chartData = [
    ...analytics.monthlyData,
    ...analytics.forecastMonths.map((f) => ({ ...f, bookings: 0 })),
  ];

  return (
    <div>
      <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-6">
        <div className="flex items-center gap-3">
          <BarChart3 className="h-6 w-6 text-primary" />
          <h1 className="text-2xl font-bold text-foreground">Revenue Analytics</h1>
        </div>
        <div className="flex items-center gap-2 flex-wrap">
          {presetRanges.map((p) => (
            <Button key={p.label} variant="outline" size="sm" onClick={() => applyPreset(p.days)}>
              {p.label}
            </Button>
          ))}
          <Popover>
            <PopoverTrigger asChild>
              <Button variant="outline" size="sm" className="gap-1.5">
                <CalendarIcon className="h-4 w-4" />
                {format(dateRange.from, "dd MMM")} – {format(dateRange.to, "dd MMM yyyy")}
              </Button>
            </PopoverTrigger>
            <PopoverContent className="w-auto p-0" align="end">
              <Calendar
                mode="range"
                selected={{ from: dateRange.from, to: dateRange.to }}
                onSelect={(range) => {
                  if (range?.from) setDateRange({ from: range.from, to: range.to || range.from });
                }}
                numberOfMonths={2}
                className={cn("p-3 pointer-events-auto")}
              />
            </PopoverContent>
          </Popover>
        </div>
      </div>

      {/* KPI cards */}
      <div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
        <Card>
          <CardContent className="pt-6">
            <div className="flex items-center justify-between">
              <p className="text-sm text-muted-foreground">Revenue (selected period)</p>
              <PoundSterling className="h-4 w-4 text-muted-foreground" />
            </div>
            <p className="text-2xl font-bold text-foreground mt-1">{fmtGBP(analytics.currentRevenue)}</p>
            <ChangeIndicator value={analytics.revenueChange} />
            <span className="text-xs text-muted-foreground ml-1">vs previous {analytics.rangeDays}d</span>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="flex items-center justify-between">
              <p className="text-sm text-muted-foreground">Bookings (selected period)</p>
              <CalendarIcon className="h-4 w-4 text-muted-foreground" />
            </div>
            <p className="text-2xl font-bold text-foreground mt-1">{analytics.currentBookings}</p>
            <ChangeIndicator value={analytics.bookingChange} />
            <span className="text-xs text-muted-foreground ml-1">vs previous {analytics.rangeDays}d</span>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="flex items-center justify-between">
              <p className="text-sm text-muted-foreground">Avg Order Value</p>
              <TrendingUp className="h-4 w-4 text-muted-foreground" />
            </div>
            <p className="text-2xl font-bold text-foreground mt-1">{fmtGBP(analytics.avgOrderValue)}</p>
            <ChangeIndicator value={analytics.aovChange} />
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="flex items-center justify-between">
              <p className="text-sm text-muted-foreground">Lifetime Revenue</p>
              <PoundSterling className="h-4 w-4 text-muted-foreground" />
            </div>
            <p className="text-2xl font-bold text-foreground mt-1">{fmtGBP(analytics.totalRevenue)}</p>
          </CardContent>
        </Card>
      </div>

      {/* Revenue trend + forecast */}
      <div className="grid lg:grid-cols-2 gap-6 mb-8">
        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">Monthly Revenue Trend & Forecast</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="h-64">
              <ResponsiveContainer width="100%" height="100%">
                <AreaChart data={chartData}>
                  <CartesianGrid strokeDasharray="3 3" className="opacity-30" />
                  <XAxis dataKey="month" tick={{ fontSize: 11 }} />
                  <YAxis tick={{ fontSize: 11 }} tickFormatter={(v) => `£${(v / 1000).toFixed(0)}k`} />
                  <Tooltip formatter={(value: number) => [`£${value.toLocaleString()}`, "Revenue"]} />
                  <Area type="monotone" dataKey="revenue" stroke="hsl(var(--primary))" fill="hsl(var(--primary) / 0.1)" strokeWidth={2} />
                </AreaChart>
              </ResponsiveContainer>
            </div>
            <p className="text-xs text-muted-foreground mt-2">
              Dashed area shows 3-month forecast based on recent trends
            </p>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">Revenue by Category</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="h-64">
              <ResponsiveContainer width="100%" height="100%">
                <BarChart data={analytics.byCategory} layout="vertical">
                  <CartesianGrid strokeDasharray="3 3" className="opacity-30" />
                  <XAxis type="number" tick={{ fontSize: 11 }} tickFormatter={(v) => `£${v.toLocaleString()}`} />
                  <YAxis type="category" dataKey="name" tick={{ fontSize: 11 }} width={100} />
                  <Tooltip formatter={(value: number) => [`£${value.toLocaleString()}`, "Revenue"]} />
                  <Bar dataKey="revenue" fill="hsl(var(--primary))" radius={[0, 4, 4, 0]} />
                </BarChart>
              </ResponsiveContainer>
            </div>
          </CardContent>
        </Card>
      </div>

      {/* Payment methods + top courses */}
      <div className="grid lg:grid-cols-2 gap-6">
        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">Revenue by Payment Method</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="space-y-3">
              {analytics.byMethod.map((m) => {
                const total = analytics.byMethod.reduce((s, x) => s + x.revenue, 0);
                const pct = total > 0 ? (m.revenue / total) * 100 : 0;
                return (
                  <div key={m.name}>
                    <div className="flex justify-between text-sm mb-1">
                      <span className="capitalize text-foreground">{m.name}</span>
                      <span className="text-muted-foreground">£{m.revenue.toLocaleString()} ({pct.toFixed(0)}%)</span>
                    </div>
                    <Progress value={pct} className="h-2" />
                  </div>
                );
              })}
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">Top Courses by Revenue</CardTitle>
          </CardHeader>
          <CardContent>
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Course</TableHead>
                  <TableHead className="text-right">Bookings</TableHead>
                  <TableHead className="text-right">Revenue</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {analytics.topCourses.map((c, i) => (
                  <TableRow key={i}>
                    <TableCell className="font-medium text-sm">{c.title}</TableCell>
                    <TableCell className="text-right">{c.bookings}</TableCell>
                    <TableCell className="text-right">{fmtGBP(c.revenue)}</TableCell>
                  </TableRow>
                ))}
                {analytics.topCourses.length === 0 && (
                  <TableRow>
                    <TableCell colSpan={3} className="text-center text-muted-foreground py-4">No data</TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      </div>
    </div>
  );
};

RevenueAnalyticsPage.layout = (page: ReactNode) => <AdminLayout>{page}</AdminLayout>;

export default RevenueAnalyticsPage;
