import { useEffect, useState } from "react";
import { addDays, format, parseISO } from "date-fns";
import {
  Area,
  AreaChart,
  CartesianGrid,
  Legend,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";

import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Spinner } from "@/components/ui/spinner";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { apiGet } from "@/lib/api";
import {
  isLikelyApiHotelBooking,
  isLikelyApiHotelRoom,
  mapApiBookingToBooking,
  mapApiRoomToRoom,
} from "@/lib/hotel-adapters";
import { formatDate, formatMoney } from "@/lib/format";
import type { BookingTrendDay, RatingSnapshot } from "@/lib/hotel-staff-types";
import { roomDisplayName } from "@/lib/room-utils";
import type { Booking, Room } from "@/lib/types";
import { useAuthStore } from "@/store/authStore";

const tooltipStyle = {
  backgroundColor: "var(--navy)",
  border: "none",
  borderRadius: "8px",
  color: "#fff",
};

type VisitSeriesResponse = {
  series: Array<{ date: string; count: number }>;
};

type ExtraRevenues = {
  roomService: string;
  laundry: string;
  gymSpa: string;
  total: string;
};

type DashboardState = {
  recentBookings: Booking[];
  visitsSeries: { date: string; views: number; sessions: number }[];
  heatmap: { roomId: string; state: "vacant" | "not_ready" | "occupied" | "unavailable" }[];
  bookingTrends: BookingTrendDay[];
  rating: RatingSnapshot | null;
  extraRevenues: ExtraRevenues | null;
  pointsSummary: { issued: number; redeemed: number } | null;
  upcoming: { id: string; title: string; date: string }[];
};

function chartDayLabel(isoDate: string) {
  try {
    return format(parseISO(isoDate), "MMM d");
  } catch {
    return isoDate;
  }
}

function ratingLabel(score: number): string {
  if (score >= 4.5) return "Impressive";
  if (score >= 3.5) return "Solid";
  if (score >= 2.5) return "Fair";
  return "Growing";
}

function mapRoomState(room: Room): "vacant" | "not_ready" | "occupied" | "unavailable" {
  switch (room.status) {
    case "occupied":
      return "occupied";
    case "maintenance":
      return "not_ready";
    case "out_of_order":
      return "unavailable";
    default:
      return "vacant";
  }
}

function shortRoomLabel(roomId: string, index: number) {
  const digits = roomId.match(/\d+/g)?.join("").slice(-2);
  if (digits) return digits.padStart(2, "0");
  return String(index + 1).padStart(2, "0");
}

export function DashboardPage() {
  const selectedPropertyId = useAuthStore((s) => s.selectedPropertyId);
  const [data, setData] = useState<DashboardState | null>(null);
  const [err, setErr] = useState<string | null>(null);

  useEffect(() => {
    let active = true;

    async function load() {
      setErr(null);
      setData(null);

      const to = new Date();
      const from = addDays(to, -14);
      const from30 = addDays(to, -30);
      const qTrends = `from=${from.toISOString()}&to=${to.toISOString()}`;
      const qExtras = `from=${from30.toISOString()}&to=${to.toISOString()}`;

      const [
        bookingsRes,
        visitsRes,
        roomsRes,
        trendsRes,
        ratingRes,
        extrasRes,
        pointsRes,
      ] = await Promise.allSettled([
        apiGet<{ data: unknown[] }>("/bookings"),
        apiGet<VisitSeriesResponse>(`/analytics/visits?${qTrends}`),
        apiGet<{ data: unknown[] }>("/rooms"),
        apiGet<BookingTrendDay[]>(`/analytics/booking-trends?${qTrends}`),
        apiGet<RatingSnapshot>("/analytics/rating"),
        apiGet<ExtraRevenues>(`/analytics/extra-revenues?${qExtras}`),
        apiGet<{ issued: number; redeemed: number }>(
          `/analytics/points-summary?${qExtras}`
        ),
      ]);

      if (!active) return;

      const next: DashboardState = {
        recentBookings: [],
        visitsSeries: [],
        heatmap: [],
        bookingTrends: [],
        rating: null,
        extraRevenues: null,
        pointsSummary: null,
        upcoming: [],
      };

      const failures: string[] = [];

      if (bookingsRes.status === "fulfilled") {
        const allBookings = bookingsRes.value.data
          .map((row) =>
            isLikelyApiHotelBooking(row) ? mapApiBookingToBooking(row) : (row as Booking)
          )
          .sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
        next.recentBookings = allBookings.slice(0, 5);
        const soon = addDays(new Date(), 14);
        next.upcoming = allBookings
          .filter(
            (b) =>
              b.status !== "cancelled" &&
              Date.parse(b.checkIn) >= Date.now() &&
              Date.parse(b.checkIn) <= soon.getTime()
          )
          .slice(0, 6)
          .map((b) => ({
            id: b.id,
            title: `${b.guest.firstName} ${b.guest.lastName} — check-in`,
            date: b.checkIn,
          }));
      } else {
        failures.push("bookings");
      }

      if (visitsRes.status === "fulfilled") {
        next.visitsSeries = visitsRes.value.series.slice(-14).map((item) => ({
          date: item.date,
          views: item.count || 0,
          sessions: 0,
        }));
      } else {
        failures.push("visits");
      }

      if (roomsRes.status === "fulfilled") {
        next.heatmap = roomsRes.value.data
          .map((row) => (isLikelyApiHotelRoom(row) ? mapApiRoomToRoom(row) : (row as Room)))
          .map((room) => ({
            roomId: room.name || room.id,
            state: mapRoomState(room),
          }));
      } else {
        failures.push("rooms");
      }

      if (trendsRes.status === "fulfilled") {
        next.bookingTrends = trendsRes.value;
      }

      if (ratingRes.status === "fulfilled") {
        next.rating = ratingRes.value;
      }

      if (extrasRes.status === "fulfilled") {
        next.extraRevenues = extrasRes.value;
      }

      if (pointsRes.status === "fulfilled") {
        next.pointsSummary = pointsRes.value;
      }

      if (failures.length === 3) {
        setErr("Unable to load dashboard data.");
        return;
      }

      setData(next);
    }

    void load();

    return () => {
      active = false;
    };
  }, [selectedPropertyId]);

  if (err) return <p className="text-destructive">{err}</p>;
  if (!data) {
    return (
      <div className="flex min-h-[400px] items-center justify-center">
        <Spinner size={32} />
      </div>
    );
  }

  const bookingChartData =
    data.bookingTrends.length > 0
      ? data.bookingTrends.map((d) => ({
          date: chartDayLabel(d.date),
          total: d.total,
          online: d.online,
          cancelled: d.cancelled,
        }))
      : [{ date: "—", total: 0, online: 0, cancelled: 0 }];

  let extraBars: { label: string; value: number; pct: number }[] = [];
  if (data.extraRevenues) {
    const room = Number(data.extraRevenues.roomService) || 0;
    const laundry = Number(data.extraRevenues.laundry) || 0;
    const gym = Number(data.extraRevenues.gymSpa) || 0;
    const maxVal = Math.max(room, laundry, gym, 1);
    extraBars = [
      { label: "Room service", value: room, pct: (room / maxVal) * 100 },
      { label: "Laundry", value: laundry, pct: (laundry / maxVal) * 100 },
      { label: "Spa / gym", value: gym, pct: (gym / maxVal) * 100 },
    ];
  }

  const ratingScore = data.rating?.averageRating ?? 0;
  const ratingDisplay =
    data.rating && data.rating.reviewCount > 0
      ? ratingScore.toFixed(1)
      : "—";
  const ratingSub =
    data.rating && data.rating.reviewCount > 0
      ? ratingLabel(ratingScore)
      : "No reviews yet";

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold tracking-tight">Dashboard</h1>
        <p className="text-muted-foreground">Bookings, visits, and property snapshot</p>
      </div>

      <div className="grid gap-4 lg:grid-cols-2">
        <Card className="rounded-2xl">
          <CardHeader className="flex flex-row items-center justify-between">
            <CardTitle className="text-base">Booking trends</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="h-[240px] w-full min-h-[220px]">
              <ResponsiveContainer width="100%" height="100%">
                <LineChart data={bookingChartData}>
                  <CartesianGrid strokeDasharray="3 3" className="opacity-40" />
                  <XAxis dataKey="date" tick={{ fontSize: 11 }} />
                  <YAxis tick={{ fontSize: 11 }} />
                  <Tooltip contentStyle={tooltipStyle} />
                  <Legend />
                  <Line
                    type="monotone"
                    dataKey="total"
                    stroke="var(--chart-1)"
                    strokeWidth={2}
                    name="Total"
                  />
                  <Line
                    type="monotone"
                    dataKey="online"
                    stroke="var(--chart-2)"
                    strokeWidth={2}
                    name="Online"
                  />
                  <Line
                    type="monotone"
                    dataKey="cancelled"
                    stroke="var(--chart-4)"
                    name="Cancelled"
                  />
                </LineChart>
              </ResponsiveContainer>
            </div>
          </CardContent>
        </Card>

        <Card className="rounded-2xl">
          <CardHeader>
            <CardTitle className="text-base">Site visits</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="h-[240px] w-full min-h-[220px]">
              <ResponsiveContainer width="100%" height="100%">
                <AreaChart data={data.visitsSeries}>
                  <CartesianGrid strokeDasharray="3 3" className="opacity-40" />
                  <XAxis dataKey="date" tick={{ fontSize: 11 }} />
                  <YAxis tick={{ fontSize: 11 }} />
                  <Tooltip contentStyle={tooltipStyle} />
                  <Area
                    type="monotone"
                    dataKey="views"
                    stroke="var(--chart-2)"
                    fill="var(--chart-3)"
                    fillOpacity={0.35}
                    name="Views"
                  />
                </AreaChart>
              </ResponsiveContainer>
            </div>
          </CardContent>
        </Card>
      </div>

      <div className="grid gap-4 lg:grid-cols-3">
        <Card className="rounded-2xl lg:col-span-2">
          <CardHeader>
            <CardTitle className="text-base">Room status</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="flex flex-wrap gap-2">
              {data.heatmap.map((h, index) => (
                <div
                  key={`${h.roomId}-${index}`}
                  title={h.roomId}
                  className="flex size-10 items-center justify-center rounded-lg border text-[10px] font-medium"
                  style={{
                    background:
                      h.state === "occupied"
                        ? "var(--chart-1)"
                        : h.state === "vacant"
                          ? "var(--chart-5)"
                          : h.state === "not_ready"
                            ? "var(--muted)"
                            : "transparent",
                    color: h.state === "occupied" ? "#fff" : "inherit",
                  }}
                >
                  {shortRoomLabel(h.roomId, index)}
                </div>
              ))}
            </div>
            <div className="mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground">
              <span className="flex items-center gap-1">
                <span className="size-2 rounded-full bg-[var(--chart-5)]" /> Vacant
              </span>
              <span className="flex items-center gap-1">
                <span className="size-2 rounded-full bg-[var(--chart-1)]" /> Occupied
              </span>
              <span className="flex items-center gap-1">
                <span className="size-2 rounded-full bg-muted" /> Not ready
              </span>
            </div>
          </CardContent>
        </Card>

        <Card className="overflow-hidden rounded-2xl">
          <CardHeader>
            <CardTitle className="text-base">Guest rating</CardTitle>
          </CardHeader>
          <CardContent className="space-y-2">
            <p className="text-4xl font-bold">{ratingDisplay}</p>
            <p className="text-sm text-muted-foreground">{ratingSub}</p>
            <img
              src="https://images.unsplash.com/photo-1566073771259-6a8506099945?auto=format&fit=crop&w=1200&q=80"
              alt="Hotel preview"
              className="mt-2 h-28 w-full rounded-xl object-cover"
            />
            <div className="flex flex-wrap gap-4 pt-2 text-sm">
              <div>
                <p className="text-muted-foreground">Discount uses</p>
                <p className="font-semibold">{data.rating?.discountUses ?? "—"}</p>
              </div>
              <div>
                <p className="text-muted-foreground">Referral bookings</p>
                <p className="font-semibold">{data.rating?.referralBookings ?? "—"}</p>
              </div>
              {data.pointsSummary && (
                <div>
                  <p className="text-muted-foreground">Points (30d)</p>
                  <p className="text-xs font-semibold">
                    +{data.pointsSummary.issued} / −{data.pointsSummary.redeemed}
                  </p>
                </div>
              )}
            </div>
          </CardContent>
        </Card>
      </div>

      <div className="grid gap-4 lg:grid-cols-2">
        <Card className="rounded-2xl">
          <CardHeader>
            <CardTitle className="text-base">Extra revenue</CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            {extraBars.length === 0 && (
              <p className="text-sm text-muted-foreground">No extra revenue in range yet.</p>
            )}
            {extraBars.map((r) => (
              <div key={r.label}>
                <div className="mb-1 flex justify-between text-sm">
                  <span>{r.label}</span>
                  <span className="text-muted-foreground">
                    {formatMoney(r.value, "ETB")} (30d)
                  </span>
                </div>
                <Progress value={Math.min(100, r.pct)} />
              </div>
            ))}
          </CardContent>
        </Card>

        <Card className="rounded-2xl">
          <CardHeader>
            <CardTitle className="text-base">Upcoming</CardTitle>
          </CardHeader>
          <CardContent className="space-y-2">
            {data.upcoming.length === 0 && (
              <p className="text-sm text-muted-foreground">
                No check-ins in the next two weeks.
              </p>
            )}
            {data.upcoming.map((e) => (
              <div
                key={e.id}
                className="rounded-xl border-l-4 border-l-primary bg-muted/30 px-3 py-2 text-sm"
              >
                <p className="font-medium">{e.title}</p>
                <p className="text-xs text-muted-foreground">{formatDate(e.date)}</p>
              </div>
            ))}
          </CardContent>
        </Card>
      </div>

      <Card className="rounded-2xl">
        <CardHeader>
          <CardTitle className="text-base">Recent bookings</CardTitle>
        </CardHeader>
        <CardContent className="hidden md:block">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Guest</TableHead>
                <TableHead>Stay</TableHead>
                <TableHead>Room type</TableHead>
                <TableHead>Status</TableHead>
                <TableHead className="text-right">Total</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {data.recentBookings.map((b) => (
                <TableRow key={b.id}>
                  <TableCell>
                    {b.guest.firstName} {b.guest.lastName}
                  </TableCell>
                  <TableCell className="text-xs text-muted-foreground">
                    {formatDate(b.checkIn)} to {formatDate(b.checkOut)}
                  </TableCell>
                  <TableCell className="text-xs">
                    {b.roomDisplayLabel ?? roomDisplayName(b.roomId)}
                  </TableCell>
                  <TableCell>
                    <Badge variant="secondary">{b.status}</Badge>
                  </TableCell>
                  <TableCell className="text-right font-medium">
                    {formatMoney(b.pricing.total)}
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </CardContent>
        <CardContent className="space-y-3 md:hidden">
          {data.recentBookings.map((b) => (
            <div key={b.id} className="rounded-xl border p-3 text-sm">
              <p className="font-medium">
                {b.guest.firstName} {b.guest.lastName}
              </p>
              <p className="text-xs text-muted-foreground">
                {formatDate(b.checkIn)} - {b.status}
              </p>
              <p className="mt-1 font-semibold">{formatMoney(b.pricing.total)}</p>
            </div>
          ))}
        </CardContent>
      </Card>
    </div>
  );
}
