"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
import { useSearchParams } from "next/navigation";
import { DateRange } from "./date-range";
import {
  DataTable,
  type Column,
  type RemoteTableState,
} from "@/components/shared/data-table";
import {
  DetailList,
  Metric,
  PreviewNotice,
  StatusBadge,
} from "@/components/shared/page";
import { Field, TextareaField } from "@/components/shared/field";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { usePreviewRole } from "@/components/layout/preview-context";
import { useDashboardAuth } from "@/components/layout/dashboard-auth-context";
import { canManage } from "@/lib/preview";
import { readListQuery } from "@/lib/list-query";
import { currency, recentDateTime } from "@/lib/format";
import { withdrawalRequests } from "./fixtures";
import {
  getWithdrawalRequest,
  getWithdrawalRequests,
  type WithdrawalPagination,
} from "./api-client";
import {
  reviewWithdrawal,
  validateTransferProof,
  withinDateRange,
  type WithdrawalRequest,
} from "./model";

const statusOptions = [
  "PENDING_APPROVAL",
  "APPROVED",
  "PROCESSING",
  "PAID",
  "REJECTED",
  "FAILED",
  "CANCELLED",
];

const initialPagination: WithdrawalPagination = {
  page: 1,
  limit: 25,
  total: 0,
  pages: 1,
};

function statusLabel(status: string) {
  return status
    .toLowerCase()
    .replaceAll("_", " ")
    .replace(/\b\w/g, (letter) => letter.toUpperCase());
}

export function WithdrawalRequests() {
  const params = useSearchParams();
  const { apiConfigured } = useDashboardAuth();
  const manage = canManage(usePreviewRole());
  const query = readListQuery(Object.fromEntries(params));
  const status = params.get("status") ?? "";
  const createdAtStart = params.get("created_at_start") ?? "";
  const createdAtEnd = params.get("created_at_end") ?? "";
  const requestedSort = params.get("sort_by") ?? "";
  const sortBy = ["created_at", "updated_at", "amount"].includes(requestedSort)
    ? requestedSort
    : "created_at";
  const sortOrder = params.get("sort_order") === "asc" ? "asc" : "desc";

  const [previewRows, setPreviewRows] = useState(withdrawalRequests);
  const [remoteRows, setRemoteRows] = useState<WithdrawalRequest[]>([]);
  const [pagination, setPagination] =
    useState<WithdrawalPagination>(initialPagination);
  const [listLoading, setListLoading] = useState(apiConfigured);
  const [listError, setListError] = useState("");
  const [refreshKey, setRefreshKey] = useState(0);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [selectedDetail, setSelectedDetail] =
    useState<WithdrawalRequest | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detailError, setDetailError] = useState("");
  const [detailRetryKey, setDetailRetryKey] = useState(0);
  const [action, setAction] = useState<
    "details" | "approve" | "reject" | "proof"
  >("details");
  const [reason, setReason] = useState("");
  const [error, setError] = useState("");
  const [notice, setNotice] = useState("");
  const [proof, setProof] = useState<{ name: string; url: string } | null>(null);

  useEffect(() => {
    if (!apiConfigured) return;
    const controller = new AbortController();
    async function load() {
      setListLoading(true);
      setListError("");
      try {
        const result = await getWithdrawalRequests(
          {
            page: query.page,
            limit: query.limit,
            search: query.search,
            status,
            createdAtStart,
            createdAtEnd,
            sortBy,
            sortOrder,
          },
          controller.signal,
        );
        setRemoteRows(result.rows);
        setPagination(result.pagination);
      } catch (err: unknown) {
        if (controller.signal.aborted) return;
        setRemoteRows([]);
        setListError(
          err instanceof Error
            ? err.message
            : "Could not load withdrawal requests.",
        );
      } finally {
        if (!controller.signal.aborted) setListLoading(false);
      }
    }
    void load();
    return () => controller.abort();
  }, [
    apiConfigured,
    query.page,
    query.limit,
    query.search,
    status,
    createdAtStart,
    createdAtEnd,
    sortBy,
    sortOrder,
    refreshKey,
  ]);

  useEffect(() => {
    if (!apiConfigured || !selectedId) return;
    const withdrawalId = selectedId;
    const controller = new AbortController();
    async function load() {
      setDetailLoading(true);
      setDetailError("");
      try {
        const detail = await getWithdrawalRequest(withdrawalId, controller.signal);
        setSelectedDetail((current) => {
          if (!current || current.id !== withdrawalId) return detail;
          return {
            ...current,
            ...detail,
            email: detail.email || current.email,
            fullName: detail.fullName || current.fullName,
            phone: detail.phone || current.phone,
          };
        });
      } catch (err: unknown) {
        if (controller.signal.aborted) return;
        setDetailError(
          err instanceof Error
            ? err.message
            : "Could not load withdrawal details.",
        );
      } finally {
        if (!controller.signal.aborted) setDetailLoading(false);
      }
    }
    void load();
    return () => controller.abort();
  }, [apiConfigured, selectedId, detailRetryKey]);

  const rows = apiConfigured ? remoteRows : previewRows;
  const visibleRows = apiConfigured
    ? remoteRows
    : previewRows.filter((row) =>
        withinDateRange(row.createdAt, createdAtStart, createdAtEnd),
      );
  const selected =
    selectedDetail?.id === selectedId
      ? selectedDetail
      : rows.find((row) => row.id === selectedId);

  function open(row: WithdrawalRequest) {
    setSelectedId(row.id);
    setSelectedDetail(row);
    setAction("details");
    setReason("");
    setError("");
    setDetailError("");
    setProof(null);
  }

  function closeDetails() {
    setSelectedId(null);
    setSelectedDetail(null);
    setDetailError("");
  }

  function submitPreviewAction() {
    if (!selected || !manage || apiConfigured) return;
    try {
      if (action === "proof" && !proof) {
        throw new Error("Choose a transfer proof image first.");
      }
      const next =
        action === "proof"
          ? { ...selected, proofName: proof!.name, proofPreview: proof!.url }
          : reviewWithdrawal(
              selected,
              action === "approve" ? "approve" : "reject",
              reason,
            );
      setPreviewRows((current) =>
        current.map((row) =>
          row.id === selected.id
            ? {
                ...next,
                ...(proof
                  ? { proofName: proof.name, proofPreview: proof.url }
                  : {}),
              }
            : row,
        ),
      );
      setNotice(
        action === "proof"
          ? "Transfer proof attached locally. No file was uploaded."
          : `${selected.id} ${action === "approve" ? "approved" : "rejected"} in this preview. No payout was initiated.`,
      );
      closeDetails();
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Unable to update the preview.",
      );
    }
  }

  const previewColumns: Column<WithdrawalRequest>[] = [
    {
      key: "createdAt",
      label: "Request Time",
      render: (row) => (
        <div>
          {recentDateTime(row.createdAt)}
          <div className="text-xs text-muted-foreground">
            {row.id} · {row.email}
          </div>
        </div>
      ),
    },
    {
      key: "bank",
      label: "Bank Details",
      render: (row) => (
        <div className="min-w-40">
          {row.bank} · {row.accountNumber}
          <div className="text-xs text-muted-foreground">{row.accountHolder}</div>
        </div>
      ),
    },
    { key: "amount", label: "Amount", render: (row) => currency(row.amount) },
    {
      key: "adminFee",
      label: "Transferred Amount",
      render: (row) => (
        <div>
          {currency(Math.max(0, row.amount - row.adminFee))}
          <div className="text-xs text-muted-foreground">
            Fee: {currency(row.adminFee)}
          </div>
        </div>
      ),
    },
    {
      key: "status",
      label: "Status",
      render: (row) => <StatusBadge>{statusLabel(row.status)}</StatusBadge>,
    },
    {
      key: "processedAt",
      label: "Processed At",
      render: (row) =>
        row.processedAt.includes("T")
          ? recentDateTime(row.processedAt)
          : row.processedAt,
    },
  ];

  const liveColumns: Column<WithdrawalRequest>[] = [
    {
      key: "createdAt",
      label: "Request Time",
      sortKey: "created_at",
      render: (row) => (
        <div>
          {recentDateTime(row.createdAt)}
          <div className="text-xs text-muted-foreground">
            {row.id}
            {row.email ? ` · ${row.email}` : ""}
          </div>
        </div>
      ),
    },
    {
      key: "bank",
      label: "Bank Details",
      sortKey: null,
      render: (row) => (
        <div className="min-w-40">
          {row.bank || "—"} · {row.accountNumber || "—"}
          <div className="text-xs text-muted-foreground">
            {row.accountHolder || "—"}
          </div>
        </div>
      ),
    },
    {
      key: "amount",
      label: "Amount",
      sortKey: "amount",
      render: (row) => currency(row.amount),
    },
    {
      key: "adminFee",
      label: "Transferred Amount",
      sortKey: null,
      render: (row) => (
        <div>
          {currency(Math.max(0, row.amount - row.adminFee))}
          <div className="text-xs text-muted-foreground">
            Fee: {currency(row.adminFee)}
          </div>
        </div>
      ),
    },
    {
      key: "status",
      label: "Status",
      sortKey: null,
      render: (row) => <StatusBadge>{statusLabel(row.status)}</StatusBadge>,
    },
    {
      key: "updatedAt",
      label: "Updated At",
      sortKey: "updated_at",
      render: (row) =>
        row.updatedAt ? recentDateTime(row.updatedAt) : "—",
    },
  ];

  const remoteTable: RemoteTableState | undefined = apiConfigured
    ? {
        ...pagination,
        loading: listLoading,
        error: listError,
        onRefresh: () => setRefreshKey((current) => current + 1),
      }
    : undefined;

  return (
    <div className="space-y-5">
      {!apiConfigured ? (
        <PreviewNotice>
          Local review preview. Approval does not transfer funds, deduct balances,
          or contact a payment gateway.
        </PreviewNotice>
      ) : (
        <p className="rounded-lg border border-info/20 bg-info/5 px-4 py-3 text-sm text-info">
          Live withdrawal requests from the payment service. This page is
          read-only.
        </p>
      )}
      {!apiConfigured && notice && (
        <p role="status" className="text-sm text-success">
          {notice}
        </p>
      )}
      {!apiConfigured && (
        <div className="grid gap-4 sm:grid-cols-3">
          <Metric
            label="Pending approval"
            value={previewRows.filter((row) => row.status === "PENDING_APPROVAL").length}
          />
          <Metric
            label="Requested amount"
            value={currency(
              previewRows
                .filter((row) => row.status === "PENDING_APPROVAL")
                .reduce((total, row) => total + row.amount, 0),
            )}
          />
          <Metric
            label="Approved"
            value={previewRows.filter((row) => row.status === "APPROVED").length}
            note="Includes sample history and local reviews"
          />
        </div>
      )}
      <DateRange />
      <DataTable
        title="Withdrawal Requests"
        description="Review bank details, requested amounts, and processing history."
        rows={visibleRows}
        remote={remoteTable}
        filters={[
          {
            key: "status",
            label: "Status",
            options: apiConfigured
              ? statusOptions
              : ["PENDING_APPROVAL", "APPROVED", "REJECTED"],
          },
          ...(!apiConfigured
            ? [{ key: "bank" as const, label: "Bank", options: ["BCA", "Mandiri", "BNI"] }]
            : []),
        ]}
        searchPlaceholder="Request, customer or bank..."
        columns={apiConfigured ? liveColumns : previewColumns}
        actions={(row) => (
          <Button variant="outline" size="sm" onClick={() => open(row)}>
            View
          </Button>
        )}
      />
      <Dialog
        open={!!selectedId}
        onOpenChange={(open) => {
          if (!open) closeDetails();
        }}
      >
        <DialogContent className="max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>
              {action === "details"
                ? "Withdrawal details"
                : action === "approve"
                  ? "Approve withdrawal"
                  : action === "reject"
                    ? "Reject withdrawal"
                    : "Transfer proof preview"}
            </DialogTitle>
            <DialogDescription>
              {selected?.id} · {apiConfigured ? "Live read-only data." : "Review actions stay local to this preview."}
            </DialogDescription>
          </DialogHeader>
          {selected && (
            <>
              <DetailList
                items={{
                  Customer: selected.fullName || "—",
                  Email: selected.email || "—",
                  Phone: selected.phone || "—",
                  "Bank account": `${selected.bank || "—"} · ${selected.accountNumber || "—"}`,
                  "Account holder": selected.accountHolder || "—",
                  "Requested amount": currency(selected.amount),
                  "Admin fee": currency(selected.adminFee),
                  "Transferred amount": currency(
                    Math.max(0, selected.amount - selected.adminFee),
                  ),
                  Status: <StatusBadge>{statusLabel(selected.status)}</StatusBadge>,
                  "Payout status": selected.payoutStatus || "—",
                  ...(selected.rejectionReason
                    ? { "Rejection reason": selected.rejectionReason }
                    : {}),
                  ...(selected.transferProofUrl
                    ? {
                        "Transfer proof": (
                          <a
                            className="text-primary underline underline-offset-2"
                            href={selected.transferProofUrl}
                            target="_blank"
                            rel="noreferrer"
                          >
                            Open proof
                          </a>
                        ),
                      }
                    : selected.proofName
                      ? { "Transfer proof": selected.proofName }
                      : {}),
                  ...(apiConfigured && selected.updatedAt
                    ? { "Updated at": recentDateTime(selected.updatedAt) }
                    : {}),
                }}
              />
              {detailLoading && (
                <p role="status" className="text-sm text-muted-foreground">
                  Loading full withdrawal details…
                </p>
              )}
              {detailError && (
                <div role="alert" className="space-y-2 text-sm text-destructive">
                  <p>{detailError}</p>
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    onClick={() => setDetailRetryKey((current) => current + 1)}
                  >
                    Retry details
                  </Button>
                </div>
              )}
              {action === "details" && selected.proofPreview && (
                <Image
                  src={selected.proofPreview}
                  alt="Attached transfer proof preview"
                  width={480}
                  height={240}
                  unoptimized
                  className="max-h-52 w-auto rounded-lg border object-contain"
                />
              )}
              {action === "reject" && (
                <TextareaField
                  label="Rejection reason"
                  required
                  value={reason}
                  onChange={(event) => setReason(event.target.value)}
                  placeholder="Explain why this request cannot be approved"
                />
              )}
              {(action === "approve" || action === "proof") && (
                <div className="space-y-3">
                  <Field
                    label={`Transfer proof${action === "approve" ? " (optional)" : ""}`}
                    type="file"
                    accept="image/jpeg,image/png,image/webp"
                    onChange={(event) => {
                      setProof(null);
                      setError("");
                      const file = event.target.files?.[0];
                      if (!file) return;
                      const failure = validateTransferProof(file);
                      if (failure) {
                        setError(failure);
                        return;
                      }
                      const reader = new FileReader();
                      reader.onload = () =>
                        setProof({ name: file.name, url: String(reader.result) });
                      reader.onerror = () =>
                        setError("Unable to read this image. Choose another file.");
                      reader.readAsDataURL(file);
                    }}
                  />
                  <p className="text-xs text-muted-foreground">
                    JPG, PNG, or WebP, up to 5 MB. Your image stays in this page.
                  </p>
                  {proof && (
                    <Image
                      src={proof.url}
                      alt="Selected transfer proof preview"
                      width={480}
                      height={240}
                      unoptimized
                      className="max-h-52 w-auto rounded-lg border object-contain"
                    />
                  )}
                </div>
              )}
              {error && (
                <p role="alert" className="text-sm text-destructive">
                  {error}
                </p>
              )}
              <DialogFooter>
                {action === "details" ? (
                  <>
                    {!apiConfigured && manage && selected.status === "PENDING_APPROVAL" && (
                      <>
                        <Button
                          type="button"
                          variant="outline"
                          onClick={() => setAction("reject")}
                        >
                          Reject
                        </Button>
                        <Button
                          type="button"
                          onClick={() => setAction("approve")}
                        >
                          Approve
                        </Button>
                      </>
                    )}
                    {!apiConfigured && manage && selected.status === "APPROVED" && (
                      <Button
                        type="button"
                        variant="outline"
                        onClick={() => setAction("proof")}
                      >
                        Attach transfer proof
                      </Button>
                    )}
                    <Button type="button" variant="outline" onClick={closeDetails}>
                      Close
                    </Button>
                  </>
                ) : (
                  <>
                    <Button
                      type="button"
                      variant="outline"
                      onClick={() => {
                        setAction("details");
                        setError("");
                      }}
                    >
                      Back
                    </Button>
                    <Button type="button" onClick={submitPreviewAction}>
                      {action === "approve"
                        ? "Confirm local approval"
                        : action === "reject"
                          ? "Confirm local rejection"
                          : "Attach locally"}
                    </Button>
                  </>
                )}
              </DialogFooter>
            </>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
