import React, { useEffect, useState, useMemo } from "react";
import { Card, Input, Pagination, Table, Tag, Button, DatePicker, Select } from "antd";
import { useNavigate } from "react-router-dom";
import type { ColumnsType } from "antd/es/table";
import { API_Instance } from "@/api/axios.instance";
import API_Constants from "@/constants/api.constants";
import toast from "react-hot-toast";
import { getAxiosErrorMessage } from "@/utils/index.utils";
import dayjs from "dayjs";
import { useAuth } from "@/hooks/useAuth";
import { Role } from "@/constants/navLink.constants";
import {
  AlertCircle,
  Calendar,
  CheckCircle,
  Clock,
  CreditCard,
  Download,
  IndianRupee,
  Search,
} from "lucide-react";
import { useDebounce } from "@/hooks/useDebounce";
import ROUTE_CONSTANTS from "@/constants/route.constants";

interface IUserBasic {
  name: string;
  email: string;
  phone: string;
}

interface IPayment {
  id: string;
  transactionId: string;
  receiptNo: string;
  user: IUserBasic;
  amount: number;
  taxableAmount: number;
  gstRate: number;
  gstAmount: number;
  cgstAmount: number;
  sgstAmount: number;
  igstAmount: number;
  gstType?: "CGST_SGST" | "IGST" | "EXEMPT" | "ZERO_RATED" | null;
  customerGstNumber?: string | null;
  method: string;
  offer: string;
  date: string;
  status: string;
  plan: string;
  institution?: string;
  institutionEmail?: string;
}

interface IPaymentSummary {
  totalTransactions: number;
  successfulPayments: number;
  pendingPayments: number;
  attentionPayments: number;
  institutionCount: number;
  totalCollected: number;
}

const filterInitial = {
  search: "",
  planType: undefined as string | undefined,
  status: undefined as string | undefined,
  startDate: undefined as string | undefined,
  endDate: undefined as string | undefined,
};

const paginationInitial = {
  page: 1,
  limit: 10,
  total: 0,
  totalPages: 0,
};

const paymentSummaryInitial: IPaymentSummary = {
  totalTransactions: 0,
  successfulPayments: 0,
  pendingPayments: 0,
  attentionPayments: 0,
  institutionCount: 0,
  totalCollected: 0,
};

const formatCurrency = (amount: number) =>
  new Intl.NumberFormat("en-IN", {
    style: "currency",
    currency: "INR",
    maximumFractionDigits: 2,
  }).format(amount || 0);

const renderTaxBreakup = (payment: IPayment) => {
  if (!payment.gstRate || !payment.gstAmount) {
    return <span className="text-xs text-slate-400">No GST</span>;
  }

  if (payment.gstType === "IGST") {
    return (
      <div className="flex flex-col text-xs leading-5">
        <span className="font-semibold text-slate-700">IGST {payment.gstRate}%</span>
        <span className="text-slate-500">{formatCurrency(payment.igstAmount || payment.gstAmount)}</span>
      </div>
    );
  }

  return (
    <div className="flex flex-col text-xs leading-5">
      <span className="font-semibold text-slate-700">CGST/SGST {payment.gstRate}%</span>
      <span className="text-slate-500">
        {formatCurrency(payment.cgstAmount)} + {formatCurrency(payment.sgstAmount)}
      </span>
    </div>
  );
};

const buildFallbackSummary = (
  records: IPayment[],
  totalTransactions: number,
): IPaymentSummary => {
  const institutionCount = new Set(
    records
      .map((payment) => payment.institution)
      .filter((institution) => institution && institution !== "N/A"),
  ).size;

  return {
    totalTransactions,
    successfulPayments: records.filter((payment) => payment.status === "SUCCESS").length,
    pendingPayments: records.filter((payment) => payment.status === "PENDING").length,
    attentionPayments: records.filter((payment) =>
      ["FAILED", "CANCELLED", "EXPIRED"].includes(payment.status),
    ).length,
    institutionCount,
    totalCollected: records
      .filter((payment) => payment.status === "SUCCESS")
      .reduce((sum, payment) => sum + Number(payment.amount || 0), 0),
  };
};

const SummaryCard = ({
  title,
  value,
  subtitle,
  icon: Icon,
  color,
}: {
  title: string;
  value: string | number;
  subtitle: string;
  icon: React.ElementType;
  color: string;
}) => (
  <div className="bg-white border border-slate-200 rounded-xl p-4 shadow-sm">
    <div className="flex items-start justify-between gap-3">
      <div className="min-w-0">
        <p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
          {title}
        </p>
        <p className="mt-2 text-2xl font-bold text-slate-900 truncate">
          {value}
        </p>
        <p className="mt-1 text-xs text-slate-500">{subtitle}</p>
      </div>
      <span className={`shrink-0 rounded-lg p-2.5 ${color}`}>
        <Icon size={20} />
      </span>
    </div>
  </div>
);

const Payments: React.FC = () => {
  const navigate = useNavigate();
  const { user } = useAuth();
  const isAdmin = user?.role === Role.ADMIN;
  const [payments, setPayments] = useState<IPayment[]>([]);
  const [loading, setLoading] = useState(false);
  const [exportLoading, setExportLoading] = useState(false); // New Export loading state
  const [pagination, setPagination] = useState(paginationInitial);
  const [summary, setSummary] = useState<IPaymentSummary>(paymentSummaryInitial);
  const [filters, setFilters] = useState(filterInitial);
  const debouncedSearch = useDebounce(filters.search, 600);
  const [downloadingId, setDownloadingId] = useState<string | null>(null);
  const [subscriptions, setSubscriptions] = useState<any[]>([]);
  const [transactionStatuses, setTransactionStatuses] = useState<string[]>([]);

  const fetchPayments = async (page = 1, limit = 10, currentFilters = filters) => {
    setLoading(true);
    try {
      const params: any = {
        page,
        limit,
        planType: currentFilters.planType,
        status: currentFilters.status,
      };

      if (currentFilters.search) {
        const searchTrim = String(currentFilters.search).trim();
        if (searchTrim) {
          params.search = searchTrim;
          const numericCandidate = searchTrim.replace(/[,₹\s]/g, "");
          const numericMatch = /^(\d+(?:\.\d+)?)$/.test(numericCandidate);
          if (numericMatch) {
            const amountDecimal = Number(numericCandidate);
            params.amount = amountDecimal;
            params.amountInPaise = Math.round(amountDecimal * 100);
          }
        }
      }

      if (currentFilters.startDate) {
        params.startDate = dayjs(currentFilters.startDate).startOf("day").toISOString();
      }
      if (currentFilters.endDate) {
        params.endDate = dayjs(currentFilters.endDate).endOf("day").toISOString();
      }
      const searchVal = currentFilters.search ? String(currentFilters.search).trim() : "";
      const numericCandidate = searchVal.replace(/[,₹\s]/g, "");
      const numericMatch = /^\d*\.?\d+$/.test(numericCandidate);

      if (numericMatch) {
        const fetchParams = { ...params, page: 1, limit: 1000 };
        delete fetchParams.search;
        delete fetchParams.amount;
        delete fetchParams.amountInPaise;
        const resAll = await API_Instance.get(API_Constants.payments, { params: fetchParams });
        const allRecords: IPayment[] = resAll.data.data || [];
        const filtered = allRecords.filter((p) => {
          const amtStr = Number(p.amount || 0).toString();
          const amtFixedStr = Number(p.amount || 0).toFixed(2);
          return amtStr.includes(numericCandidate) || amtFixedStr.includes(numericCandidate);
        });

        setPayments(filtered);
        setPagination({ page: 1, limit: paginationInitial.limit, total: filtered.length, totalPages: Math.max(1, Math.ceil(filtered.length / paginationInitial.limit)) });
        setSummary(
          buildFallbackSummary(filtered, filtered.length),
        );

        setLoading(false);
        return;
      }

      const res = await API_Instance.get(API_Constants.payments, { params });
      setPayments(res.data.data);
      setPagination(res.data.meta || { ...paginationInitial, page, limit });
      setSummary(
        res.data.meta?.summary ||
        buildFallbackSummary(res.data.data, res.data.meta?.total || 0),
      );
    } catch (error) {
      toast.error(getAxiosErrorMessage(error));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    const fetchData = async () => {
      try {
        const params: any = { limit: 1000, includeHidden: true };
        const [subRes, statusRes] = await Promise.all([
          API_Instance.get(API_Constants.subscriptionPlans, { params }),
          API_Instance.get(`${API_Constants.payments}/statuses`),
        ]);
        setSubscriptions(subRes.data.data);
        setTransactionStatuses(statusRes.data.data);
      } catch (error) {
        console.error("Error fetching data for filters:", error);
      }
    };
    fetchData();
  }, []);

  useEffect(() => {
    const updatedFilters = { ...filters, search: debouncedSearch };
    fetchPayments(1, pagination.limit, updatedFilters);
  }, [debouncedSearch, filters.planType, filters.status, filters.startDate, filters.endDate, pagination.limit]);

  const subscriptionOptions = React.useMemo(() => {
    return Array.from(
      new Map(
        subscriptions
          .filter((p: any) => (p.isActive || p.planType.toLowerCase() === 'trial') && p.planName && p.planType)
          .map((p: any) => [p.planType, p.planName])
      )
    ).map(([planType, planName]) => ({
      label: planName,
      value: planType,
    }));
  }, [subscriptions]);

  const statusOptions = useMemo(() => {
    return transactionStatuses
      .filter((status: string) => !["REFUNDED", "PARTIAL_REFUND", "PROCESSING"].includes(status))
      .map((status: string) => ({
        label: status.charAt(0).toUpperCase() + status.slice(1).toLowerCase().replace('_', ' '),
        value: status,
      }));
  }, [transactionStatuses]);

  const handleDownloadReceipt = async (id: string) => {
    try {
      setDownloadingId(id);
      const res = await API_Instance.get(
        `${API_Constants.payments}/${id}/download-receipt`,
        { responseType: "blob" },
      );

      const file = new Blob([res.data], { type: "application/pdf" });
      const fileURL = window.URL.createObjectURL(file);
      window.open(fileURL, "_blank");

      setTimeout(() => {
        window.URL.revokeObjectURL(fileURL);
      }, 1000);
    } catch (error) {
      toast.error("Failed to open receipt");
    } finally {
      setDownloadingId(null);
    }
  };

  const handleExportPDF = async () => {
    if (payments.length === 0) {
      toast.error("No data available to export.");
      return;
    }
    setExportLoading(true);
    try {
      const params: any = {
        planType: filters.planType,
        status: filters.status,
      };

      if (filters.search) {
        const searchTrim = String(filters.search).trim();
        if (searchTrim) {
          params.search = searchTrim;

          const numericCandidate = searchTrim.replace(/[,₹\s]/g, "");
          const numericMatch = /^(\d+(?:\.\d+)?)$/.test(numericCandidate);
          if (numericMatch) {
            const amountDecimal = Number(numericCandidate);
            params.amount = amountDecimal;
            params.amountInPaise = Math.round(amountDecimal * 100);
          }
        }
      }

      if (filters.startDate) params.startDate = dayjs(filters.startDate).startOf("day").toISOString();
      if (filters.endDate) params.endDate = dayjs(filters.endDate).endOf("day").toISOString();

      const res = await API_Instance.get(`${API_Constants.payments}/payment-report-pdf`, {
        params,
        responseType: "blob",
      });

      const blob = new Blob([res.data], { type: "application/pdf" });
      const downloadUrl = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = downloadUrl;
      link.download = `Payment_History_Report_${dayjs().format("YYYY-MM-DD")}.pdf`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(downloadUrl);

      toast.success("PDF Exported Successfully");
    } catch (error) {
      toast.error("Failed to export PDF report");
    } finally {
      setExportLoading(false);
    }
  };

  const columns: ColumnsType<IPayment> = [
    {
      title: "Receipt Info",
      key: "receiptNo",
      render: (_, record) => (
        <div className="flex flex-col">
          <span className="font-medium text-slate-700">
            Receipt: {record.receiptNo || "N/A"}
          </span>
          <span className="text-xs text-slate-500 uppercase">
            Payment Mode: {record.method || "N/A"}
          </span>
        </div>
      ),
    },
    {
      title: "Payment Amount",
      dataIndex: "amount",
      key: "amount",
      render: (amount) => (
        <span className="font-semibold text-green-600">
          {formatCurrency(amount)}
        </span>
      ),
    },
    {
      title: "Tax Details",
      key: "tax",
      width: 170,
      render: (_, record) => (
        <div className="flex flex-col gap-1">
          <span className="text-xs text-slate-500">
            Taxable: {formatCurrency(record.taxableAmount || record.amount)}
          </span>
          {renderTaxBreakup(record)}
        </div>
      ),
    },
    {
      title: "Subscription Plan",
      dataIndex: "plan",
      key: "plan",
      render: (plan) => (
        <Tag color="blue" className="uppercase">
          {plan}
        </Tag>
      ),
    },
    {
      title: "Date",
      dataIndex: "date",
      key: "date",
      render: (date) => (
        <div className="flex items-center gap-1 text-slate-500">
          <Calendar size={14} />
          <span>{dayjs(date).format("DD MMM YYYY, hh:mm A")}</span>
        </div>
      ),
    },
    {
      title: "Status",
      dataIndex: "status",
      key: "status",
      render: (status: string) => {
        const statusConfig: Record<string, { color: string; label: string }> = {
          SUCCESS: { color: "success", label: "Success" },
          PENDING: { color: "processing", label: "Pending" },
          FAILED: { color: "error", label: "Failed" },
          CANCELLED: { color: "error", label: "Cancelled" },
          EXPIRED: { color: "warning", label: "Expired" },
          REFUNDED: { color: "magenta", label: "Refunded" },
          PARTIAL_REFUND: { color: "volcano", label: "Partial Refund" },
        };
        const config = statusConfig[status] || { color: "default", label: status };
        return <Tag color={config.color}>{config.label}</Tag>;
      },
    },
    {
      title: "Actions",
      key: "action",
      width: 150,
      render: (_, record) => (
        <div className="flex gap-2">
          <Button
            type="link"
            size="small"
            className="text-blue-600 hover:text-blue-700 font-semibold p-0"
            onClick={() => navigate(ROUTE_CONSTANTS.PaymentDetail.replace(":transactionId", record.id))}
          >
            View
          </Button>
          {record.status === "SUCCESS" && (
            <>
              <span className="text-slate-300">|</span>
              <Button
                type="link"
                size="small"
                className="text-emerald-600 hover:text-emerald-700 font-semibold p-0"
                onClick={() => handleDownloadReceipt(record.id)}
                loading={downloadingId === record.id}
              >
                Receipt
              </Button>
            </>
          )}
        </div>
      ),
    },
  ];

  return (
    <div className="flex flex-col gap-4 px-4 py-6">
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
        <div>
          <h2 className="text-2xl font-bold text-slate-800 flex items-center gap-2">
            <CreditCard className="text-blue-600" /> Payment History
          </h2>
          <p className="text-slate-500 text-sm mt-1">
            View institution billing, receipts, subscription plans, and payment status.
          </p>
        </div>

        <Button
          type="primary"
          disabled={exportLoading}
          onClick={handleExportPDF}
          className="bg-blue-600 hover:bg-blue-700 hover:text-white flex items-center gap-2 rounded-lg font-medium"
          icon={<Download size={16} />}
          loading={exportLoading}
        >
          {exportLoading ? "Generating PDF..." : "Export PDF"}
        </Button>
      </div>

      <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
        <SummaryCard
          title="Total Payments"
          value={summary.totalTransactions.toLocaleString("en-IN")}
          subtitle="Transactions in current filters"
          icon={CreditCard}
          color="bg-blue-50 text-blue-600"
        />
        <SummaryCard
          title={filters.status ? `${filters.status.charAt(0).toUpperCase() + filters.status.slice(1).toLowerCase()} Amount` : "Collected"}
          value={formatCurrency(summary.totalCollected)}
          subtitle={filters.status ? `${filters.status.charAt(0).toUpperCase() + filters.status.slice(1).toLowerCase()} payments` : "Successful payments"}
          icon={IndianRupee}
          color="bg-emerald-50 text-emerald-600"
        />
        <SummaryCard
          title="Successful"
          value={summary.successfulPayments.toLocaleString("en-IN")}
          subtitle="Completed transactions"
          icon={CheckCircle}
          color="bg-green-50 text-green-600"
        />
        <SummaryCard
          title="Pending | Issues"
          value={`Pending: ${summary.pendingPayments.toLocaleString("en-IN")} | Issues: ${summary.attentionPayments.toLocaleString("en-IN")}`}
          subtitle="Pending and failed records"
          icon={summary.attentionPayments > 0 ? AlertCircle : Clock}
          color={
            summary.attentionPayments > 0
              ? "bg-rose-50 text-rose-600"
              : "bg-amber-50 text-amber-600"
          }
        />
      </div>

      <Card className="shadow-sm border border-slate-200 rounded-xl">
        <div className="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4 mb-4">
          <div className="flex flex-col sm:flex-row items-center gap-3 w-full">
            <Input
              placeholder="Search receipt, amount, mode..."
              prefix={<Search size={16} className="text-slate-400" />}
              allowClear
              value={filters.search}
              onChange={(e) => setFilters({ ...filters, search: e.target.value })}
              className="w-full"
            />

            <Select
              placeholder="Subscription Plan"
              className="w-full"
              allowClear
              value={filters.planType}
              onChange={(val) => setFilters({ ...filters, planType: val })}
              options={subscriptionOptions}
            />

            <Select
              placeholder="Transaction Status"
              className="w-full"
              allowClear
              value={filters.status}
              onChange={(val) => setFilters({ ...filters, status: val })}
              options={statusOptions}
            />

            <DatePicker.RangePicker
              value={filters.startDate && filters.endDate ? [dayjs(filters.startDate), dayjs(filters.endDate)] : null}
              disabledDate={(current) => current && current > dayjs().endOf("day")}
              onChange={(dates) => {
                setFilters({
                  ...filters,
                  startDate: dates && dates[0] ? dates[0].toISOString() : undefined,
                  endDate: dates && dates[1] ? dates[1].toISOString() : undefined,
                });
              }}
              className="w-full"
            />

            {(filters.search || filters.planType || filters.status || filters.startDate) && (
              <Button
                onClick={() => setFilters({
                  search: "",
                  planType: undefined,
                  status: undefined,
                  startDate: undefined,
                  endDate: undefined
                })}
              >
                Clear
              </Button>
            )}
          </div>
          <div className="text-slate-500 text-sm whitespace-nowrap mt-4 lg:mt-0">
            Matching payments:{" "}
            <span className="font-semibold text-slate-800">
              {pagination.total}
            </span>
          </div>
        </div>

        <Table
          columns={columns}
          dataSource={payments}
          loading={loading}
          rowKey="id"
          pagination={false}
          scroll={{ x: 1000 }}
          className="border border-slate-100 rounded-lg overflow-hidden"
          locale={{
            emptyText: "No institution payments found",
          }}
        />

        <div className="flex justify-end mt-4">
          <Pagination
            current={pagination.page}
            total={pagination.total}
            pageSize={pagination.limit}
            onChange={(page, pageSize) => {
              setPagination((prev) => ({ ...prev, page, limit: pageSize }));
              fetchPayments(page, pageSize, filters);
            }}
            showSizeChanger
            showTotal={(total) => `Total ${total} payments`}
          />
        </div>
      </Card>
    </div>
  );
};

export default Payments;
