"use client";

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Megaphone } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Pagination } from "@/components/shared/pagination";
import { EmptyState, ErrorState, TableSkeleton } from "@/components/shared/states";
import { PushBroadcastStatusBadge } from "@/features/push/push-badges";
import { getPushBroadcast, getPushBroadcasts } from "@/services/push";
import { queryKeys } from "@/lib/query-keys";
import { useUrlState } from "@/lib/use-url-state";
import { useI18n, useT } from "@/i18n";
import { formatDateTime } from "@/lib/format";
import { friendlyErrorMessage } from "@/lib/errors";
import { cn } from "@/lib/cn";
import type { Locale } from "@/i18n/types";
import type { PushBroadcast } from "@/types/push";

function ReachBar({ reached, target }: { reached: number; target: number }) {
  const percent = target > 0 ? Math.min(100, Math.round((reached / target) * 100)) : 0;
  return (
    <div className="min-w-28">
      <div className="h-1.5 w-full overflow-hidden rounded-full bg-muted">
        <div
          className={cn("h-full rounded-full", percent === 100 ? "bg-success" : "bg-primary")}
          style={{ width: `${percent}%` }}
        />
      </div>
      <p className="numeric mt-1 text-xs text-muted-foreground">
        {reached} / {target}
      </p>
    </div>
  );
}

export function BroadcastsTab() {
  const t = useT();
  const { locale } = useI18n();
  const [page, setPage] = useUrlState("bc_page", 1, (value) => {
    const n = Number(value);
    return Number.isFinite(n) && n >= 1 ? n : null;
  });
  const [detail, setDetail] = useState<PushBroadcast | null>(null);

  const filters = { page, rows: 10 };
  const query = useQuery({
    queryKey: queryKeys.push.broadcasts(filters),
    queryFn: () => getPushBroadcasts(filters),
  });

  const broadcasts = query.data?.Model ?? [];

  return (
    <Card>
      {query.isPending ? (
        <TableSkeleton rows={8} cols={6} />
      ) : query.isError ? (
        <ErrorState message={friendlyErrorMessage(query.error, t)} onRetry={() => query.refetch()} />
      ) : broadcasts.length === 0 ? (
        <EmptyState title={t("push.emptyBroadcasts")} description={t("push.emptyBroadcastsHint")} icon={Megaphone} />
      ) : (
        <>
          <div className="overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>{t("push.titleField")}</TableHead>
                  <TableHead>{t("push.audience")}</TableHead>
                  <TableHead>{t("push.reached")}</TableHead>
                  <TableHead>{t("common.status")}</TableHead>
                  <TableHead>{t("push.sentBy")}</TableHead>
                  <TableHead>{t("common.createdAt")}</TableHead>
                  <TableHead aria-label={t("common.actions")} />
                </TableRow>
              </TableHeader>
              <TableBody>
                {broadcasts.map((broadcast) => (
                  <TableRow key={broadcast.uuid}>
                    <TableCell>
                      <p className="max-w-56 truncate font-medium text-foreground">{broadcast.title}</p>
                      <p className="max-w-56 truncate text-xs text-muted-foreground">{broadcast.body}</p>
                    </TableCell>
                    <TableCell>
                      <Badge variant="accent">{broadcast.audience_label}</Badge>
                    </TableCell>
                    <TableCell>
                      <ReachBar reached={broadcast.counts.reached} target={broadcast.target_count} />
                    </TableCell>
                    <TableCell>
                      <PushBroadcastStatusBadge status={broadcast.status} label={broadcast.status_label} />
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {broadcast.sent_by?.name ?? "—"}
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {formatDateTime(broadcast.created_at, locale)}
                    </TableCell>
                    <TableCell>
                      <Button variant="outline" size="sm" onClick={() => setDetail(broadcast)}>
                        {t("push.details")}
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
          <Pagination page={query.data!.Page} totalPages={query.data!.Total} records={query.data!.Records} onPageChange={setPage} />
        </>
      )}

      <Dialog open={detail !== null} onOpenChange={(next) => !next && setDetail(null)}>
        <DialogContent className="max-w-lg">
          {detail ? <BroadcastDetail broadcast={detail} locale={locale} /> : null}
        </DialogContent>
      </Dialog>
    </Card>
  );
}

/**
 * One broadcast, kept up to date while it is still going out.
 *
 * A broadcast to the whole fleet is not instant — it is a queued job per device — so the reached
 * and failed counts on the row are a snapshot from whenever the list was fetched. While the
 * broadcast is unfinished this re-reads it, which is the difference between watching a send and
 * reloading the page to find out whether it worked.
 */
function BroadcastDetail({ broadcast, locale }: { broadcast: PushBroadcast; locale: Locale }) {
  const t = useT();
  const unfinished = broadcast.finished_at === null && broadcast.status !== "completed";

  const query = useQuery({
    queryKey: queryKeys.push.broadcast(broadcast.uuid),
    queryFn: async () => (await getPushBroadcast(broadcast.uuid)).Model ?? null,
    // Polled only while there is something left to watch; a finished broadcast never changes again,
    // and the row already holds everything it will ever say.
    refetchInterval: unfinished ? 3000 : false,
    enabled: unfinished,
  });

  const detail = query.data ?? broadcast;

  return (
    <>
      <DialogHeader>
        <DialogTitle>{detail.title}</DialogTitle>
        <DialogDescription>{detail.status_label}</DialogDescription>
      </DialogHeader>
      <div className="space-y-4 text-sm">
        <p className="text-muted-foreground">{detail.body}</p>
        <dl className="grid grid-cols-2 gap-x-4 gap-y-3">
          <div>
            <dt className="text-xs text-muted-foreground">{t("push.audience")}</dt>
            <dd className="font-medium">{detail.audience_label}</dd>
          </div>
          <div>
            <dt className="text-xs text-muted-foreground">{t("push.target")}</dt>
            <dd className="numeric font-medium">{detail.target_count}</dd>
          </div>
          <div>
            <dt className="text-xs text-muted-foreground">{t("push.reached")}</dt>
            <dd className="numeric font-medium">{detail.counts.reached}</dd>
          </div>
          <div>
            <dt className="text-xs text-muted-foreground">{t("push.failed")}</dt>
            <dd className="numeric font-medium">{detail.counts.failed}</dd>
          </div>
          <div>
            <dt className="text-xs text-muted-foreground">{t("push.sentBy")}</dt>
            <dd className="font-medium">{detail.sent_by?.name ?? "—"}</dd>
          </div>
          <div>
            <dt className="text-xs text-muted-foreground">{t("common.createdAt")}</dt>
            <dd className="text-muted-foreground">{formatDateTime(detail.created_at, locale)}</dd>
          </div>
        </dl>
        {unfinished ? <p className="text-xs text-muted-foreground">{t("push.stillSending")}</p> : null}
      </div>
    </>
  );
}