"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { DataTable } from "@/components/datatable/data-table";
import {
  createAllTransactionsColumns,
  AllTransactions,
  getEditRoute,
  getDeleteEndpoint,
} from "@/components/datatable/alltransactions/page";
import { PageHeader } from "@/components/ui/PageHeader";
import { AllTransactionsModal } from "@/components/cash/AllTransactionsModal";
import { AllTransactionsActions } from "@/components/cash/AllTransactionsActions";
import { DeleteConfirmModal } from "@/components/cash/DeleteConfirmModal";
import { BREADCRUMBS } from "@/constants/breadcrumbs";
import { formatNumber, parseNumber } from "@/lib/common";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";

const toString = (value: unknown): string =>
  value === null || value === undefined ? "" : String(value);

const stripHtmlTags = (html: string): string => {
  if (!html) return html;
  return html
    .replace(/<[^>]*>/g, "")
    .replace(/&nbsp;/g, " ")
    .replace(/&amp;/g, "&")
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/&quot;/g, '"')
    .replace(/&#39;/g, "'")
    .trim();
};

const pickStringFromCandidates = (
  item: Record<string, any>,
  keys: string[]
): string => {
  const sources = [
    item,
    item?.attributes ?? {},
    item?.data ?? {},
    item?.meta ?? {},
  ];

  for (const source of sources) {
    for (const key of keys) {
      const value = source?.[key];
      if (value !== undefined && value !== null && String(value).trim() !== "") {
        return String(value);
      }
    }
  }
  return "";
};

const normalizeTransactions = (payload: unknown): AllTransactions[] => {
  const candidateSources = [
    (payload as any)?.data?.data,
    (payload as any)?.data,
    (payload as any)?.records,
    (payload as any)?.items,
    payload,
  ];

  const fallback = candidateSources.find((entry) => Array.isArray(entry)) as any[] | undefined;

  if (!Array.isArray(fallback)) {
    return [];
  }

  return fallback.map((item, index) => {
    const rawAmount = toString(item?.amount ?? item?.net_amount ?? item?.total);
    const cleanAmount = stripHtmlTags(rawAmount);
    const fallbackId = `txn-${index + 1}`;
    
    return {
      id: toString(
        item?.id ??
          item?.uid ??
          item?.transaction_id ??
          item?.reference ??
          item?.txn_id ??
          item?.tref ??
          fallbackId
      ),
      uid: toString(item?.uid ?? item?.id ?? fallbackId),
      t_date: toString(item?.t_date ?? item?.trade_date),
      bank_id: toString(item?.bank_id ?? item?.bank ?? item?.bank_name ?? ""),
      ticker: toString(item?.ticker ?? item?.security ?? item?.symbol ?? ""),
      isin: toString(item?.isin ?? item?.securityname ?? item?.name ?? ""),
      f_type: toString(item?.f_type ?? item?.category ?? item?.type ?? ""),
      price: toString(item?.price ?? item?.trade_price ?? ""),
      quantity: toString(item?.quantity ?? item?.units ?? ""),
      purchase_currency_code: toString(item?.purchase_currency_code ?? item?.currency ?? item?.currency_code ?? ""),
      amount: cleanAmount,
      updateUrl: item?.updateUrl ?? item?.stockUpdateUrl ?? item?.editUrl ?? item?.update_url ?? undefined,
      f_type2: item?.f_type2 ?? item?.fType2 ?? item?.sub_type ?? item?.subType ?? undefined,
      file_url: item?.file_url ?? item?.fileUrl ?? undefined,
      file: item?.file ?? undefined,
      r_link: item?.r_link ?? item?.rLink ?? undefined,
      document: item?.document ?? undefined,
      document_url: item?.document_url ?? item?.documentUrl ?? undefined,
      file_path: item?.file_path ?? undefined,
      filePath: item?.filePath ?? undefined,
      remark: item?.remark ?? null,
      purpose: item?.purpose ?? null,
      commission: toString(
        pickStringFromCandidates(item, [
          "commission",
          "brokerage",
          "brokerage_commission",
          "commission_amount",
          "brokerage_amount",
          "transactioncost",
          "transaction_cost",
          "c_1",
        ])
      ),
      chargesandfees: toString(
        pickStringFromCandidates(item, [
          "chargesandfees",
          "charges_and_fees",
          "charges",
          "chargesandfeesabroad",
          "charges_and_fees_abroad",
          "bankfees",
          "bank_fees",
          "b_1",
        ])
      ),
      federalturnovertax: toString(
        pickStringFromCandidates(item, [
          "federalturnovertax",
          "federal_turnover_tax",
          "federal_turn_over_tax",
          "federalturnovertaxamount",
          "federal_turnover_tax_amount",
          "tax",
          "b_2",
        ])
      ),
    };
  });
};

const NON_POSITION_CLASS_KEYWORDS = ["interest", "dividend", "fee", "tax", "commission", "charges"];

const isPositionClass = (className: string): boolean => {
  const normalized = className.toLowerCase();
  return !NON_POSITION_CLASS_KEYWORDS.some((keyword) => normalized.includes(keyword));
};

const sumNetPositionQuantityByReference = (rows: AllTransactions[]): number => {
  const quantityByReference = new Map<string, number>();
  for (const row of rows) {
    const key = (row.uid || row.id || "").trim();
    if (!key) continue;

    // Ignore non-position rows like dividends/fees/taxes in quantity totals.
    if (!isPositionClass(row.f_type || "")) continue;

    const qty = Math.abs(parseNumber(row.quantity));
    const isSale = (row.f_type || "").toLowerCase().includes("sale");
    const signedQty = isSale ? -qty : qty;
    quantityByReference.set(key, (quantityByReference.get(key) || 0) + signedQty);
  }
  return Array.from(quantityByReference.values()).reduce((sum, qty) => sum + qty, 0);
};

const getSignedQuantity = (row: AllTransactions): number => {
  const qty = Math.abs(parseNumber(row.quantity));
  const isSale = (row.f_type || "").toLowerCase().includes("sale");
  return isSale ? -qty : qty;
};

const formatModalAmount = (value: number): string =>
  formatNumber(value, { minimumFractionDigits: 2, maximumFractionDigits: 3 });

export default function ListTransaction() {
  const router = useRouter();
  const [data, setData] = useState<AllTransactions[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);
  const [selectedTransaction, setSelectedTransaction] = useState<AllTransactions | null>(null);
  const [showModal, setShowModal] = useState(false);
  const [filteredData, setFilteredData] = useState<AllTransactions[]>([]);
  const [showSummaryModal, setShowSummaryModal] = useState(false);
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
  const [deleteLoading, setDeleteLoading] = useState(false);

  const fetchTransactions = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch("/api/equity/alltransactions", {
        method: "GET",
        credentials: "include",
      });

      if (!response.ok) {
        const detail = await response.text();
        throw new Error(
          `Failed to fetch transactions (${response.status}): ${detail || "No response body"}`
        );
      }

      const payload = await response.json();
      const normalized = normalizeTransactions(payload);
      setData(normalized);
    } catch (fetchError) {
      console.error("Unable to load transactions:", fetchError);
      setError(
        fetchError instanceof Error ? fetchError.message : "Unexpected error while fetching data."
      );
      setData([]);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchTransactions();
  }, [fetchTransactions]);

  const handleEdit = useCallback(() => {
    if (!selectedTransaction) return;
    const referencedId = selectedTransaction.id ?? selectedTransaction.uid;
    const editRoute = getEditRoute(selectedTransaction.f_type, referencedId, selectedTransaction.updateUrl, selectedTransaction.f_type2);
    if (editRoute) {
      setShowModal(false);
      router.push(editRoute);
    }
  }, [selectedTransaction, router]);

  const handleView = useCallback((record: AllTransactions) => {
    setSelectedTransaction(record);
    setShowModal(true);
  }, []);

  const closeModal = useCallback(() => {
    setShowModal(false);
    setSelectedTransaction(null);
  }, []);

  const handleDeleteClick = useCallback(() => {
    if (!selectedTransaction) return;
    setShowDeleteConfirm(true);
  }, [selectedTransaction]);

  const handleCancelDelete = useCallback(() => {
    setShowDeleteConfirm(false);
  }, []);

  const confirmDelete = useCallback(async () => {
    if (!selectedTransaction) return;
    const referencedId = selectedTransaction.id ?? selectedTransaction.uid;
    if (!referencedId) return;

    setDeleteLoading(true);
    try {
      const query = new URLSearchParams({ id: referencedId });
      if (selectedTransaction.f_type) {
        query.set("f_type", selectedTransaction.f_type);
      }

      const deleteEndpoint = getDeleteEndpoint(
        selectedTransaction.f_type ?? "",
        selectedTransaction.f_type2
      );

      const response = await fetch(`${deleteEndpoint}?${query.toString()}`, {
        method: "DELETE",
        credentials: "include",
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(
          `Delete failed with status ${response.status}: ${errorText || response.statusText}`
        );
      }

      const result = await response.json();
      if (result?.status === "error") {
        throw new Error(result.error || result.message || "Delete failed");
      }

      setShowDeleteConfirm(false);
      closeModal();
      await fetchTransactions();
    } catch (deleteError) {
      console.error("Unable to delete transaction:", deleteError);
      setError(
        deleteError instanceof Error
          ? deleteError.message
          : "Unexpected error while deleting transaction."
      );
    } finally {
      setDeleteLoading(false);
    }
  }, [selectedTransaction, closeModal, fetchTransactions]);

  const allTransactionColumns = useMemo(
    () => createAllTransactionsColumns({ onView: handleView }, data),
    [handleView, data]
  );

  const modalCurrency = useMemo(
    () =>
      filteredData.find((item) => (item.purchase_currency_code || "").trim())?.purchase_currency_code ||
      "USD",
    [filteredData]
  );

  const tickerSummary = useMemo(() => {
    const uniqueNames = new Set(
      filteredData.map((item) => (item.isin || "").trim()).filter(Boolean)
    );
    const amount = filteredData.reduce((sum, item) => sum + parseNumber(item.amount), 0);
    return {
      name:
        uniqueNames.size > 1
          ? "Various"
          : filteredData.find((item) => (item.ticker || "").trim())?.ticker || "—",
      quantity: sumNetPositionQuantityByReference(filteredData),
      amount,
    };
  }, [filteredData]);

  const classSummary = useMemo(() => {
    const nonPosition = new Map<string, number>();
    const positionRows: Array<{ label: string; quantity: number; amount: number }> = [];

    for (const row of filteredData) {
      const key = (row.f_type || "").trim() || "Unknown";
      const amount = parseNumber(row.amount);
      if (isPositionClass(key)) {
        positionRows.push({
          label: key,
          quantity: getSignedQuantity(row),
          amount,
        });
      } else {
        nonPosition.set(key, (nonPosition.get(key) || 0) + amount);
      }
    }

    const nonPositionRows = Array.from(nonPosition.entries()).map(([label, amount]) => ({
      label,
      quantity: 0,
      amount,
    }));

    return [...nonPositionRows, ...positionRows];
  }, [filteredData]);

  const feeSummary = useMemo(() => {
    return {
      commission: filteredData.reduce((sum, row) => sum + parseNumber(row.commission), 0),
      charges: filteredData.reduce((sum, row) => sum + parseNumber(row.chargesandfees), 0),
      tax: filteredData.reduce((sum, row) => sum + parseNumber(row.federalturnovertax), 0),
    };
  }, [filteredData]);

  return (
    <div className="container mx-auto px-4 mt-10 pb-12">
      <PageHeader
        title="All Transactions"
        description="Unified view of every executed transaction across asset classes."
        breadcrumbs={[...BREADCRUMBS.allTransactions]}
        actions={<AllTransactionsActions isLoading={loading} onRefresh={fetchTransactions} />}
      />

      {error && (
        <div className="mb-5 flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-xs text-red-700 shadow-sm animate-[fadeIn_0.3s_ease-in-out]">
          <span className="mt-0.5 inline-block h-1.5 w-1.5 flex-shrink-0 rounded-full bg-red-400" />
          {error}
        </div>
      )}

      {/* Skeleton while loading */}
      {loading ? (
        <div className="overflow-hidden rounded-2xl border border-slate-200/80 bg-white shadow-sm">
          {/* Header skeleton */}
          <div className="border-b border-slate-100 bg-slate-50/70 px-4 py-3 flex gap-6">
            {Array.from({ length: 7 }).map((_, i) => (
              <div key={i} className="h-3 rounded-full bg-slate-200 animate-pulse" style={{ width: `${60 + (i % 3) * 20}px`, animationDelay: `${i * 40}ms` }} />
            ))}
          </div>
          {/* Row skeletons */}
          {Array.from({ length: 12 }).map((_, i) => (
            <div key={i} className={`flex gap-6 px-4 py-3 border-b border-slate-50 ${i % 2 === 0 ? "bg-white" : "bg-slate-50/40"}`}>
              {Array.from({ length: 7 }).map((_, j) => (
                <div key={j} className="h-3 rounded-full bg-slate-100 animate-pulse" style={{ width: `${50 + ((i + j) % 4) * 18}px`, animationDelay: `${(i * 7 + j) * 20}ms` }} />
              ))}
            </div>
          ))}
        </div>
      ) : (
        <DataTable
          columns={allTransactionColumns}
          data={data}
          onFilteredDataChange={setFilteredData}
          summaryConfig={{
            quantityKey: "quantity",
            amountKey: "amount",
            currencyKey: "purchase_currency_code",
            quantityUniqueByKey: "uid",
            quantityUniqueByKeys: ["uid", "id"],
            customQuantityTotal: (rows) => sumNetPositionQuantityByReference(rows as AllTransactions[]),
            onView: () => setShowSummaryModal(true),
          }}
        />
      )}

      {showModal && selectedTransaction && (
        <AllTransactionsModal
          transaction={selectedTransaction}
          onClose={closeModal}
          onEdit={handleEdit}
          onDelete={handleDeleteClick}
        />
      )}

      {showDeleteConfirm && selectedTransaction && (
        <DeleteConfirmModal
          record={{
            ...selectedTransaction,
            ticker: selectedTransaction.ticker ?? undefined,
            isin: selectedTransaction.isin ?? undefined,
          }}
          onCancel={handleCancelDelete}
          onConfirm={confirmDelete}
          deleteLoading={deleteLoading}
        />
      )}

      <Dialog open={showSummaryModal} onOpenChange={setShowSummaryModal}>
        <DialogContent className="sm:max-w-[760px] overflow-hidden border border-white/30 bg-white/95 p-0 text-slate-700 shadow-2xl">
          <DialogHeader className="border-b border-slate-100 bg-gradient-to-r from-[#428B4D]/5 via-white to-white px-6 py-4">
            <DialogTitle className="text-lg font-semibold text-slate-800">Transactions</DialogTitle>
          </DialogHeader>

          <div className="space-y-4 bg-white px-4 py-4 text-slate-700">
            <table className="w-full border border-slate-200 text-sm text-slate-700">
              <thead className="bg-slate-50 text-slate-800">
                <tr>
                  <th className="border border-slate-200 px-3 py-2 text-left text-sm font-semibold text-slate-800">Security Ticker Name</th>
                  <th className="border border-slate-200 px-3 py-2 text-left text-sm font-semibold text-slate-800">Quantity</th>
                  <th className="border border-slate-200 px-3 py-2 text-right text-sm font-semibold text-slate-800">Total Amount</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">{tickerSummary.name}</td>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">{formatNumber(tickerSummary.quantity)}</td>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-right text-slate-700">
                    {modalCurrency} {formatModalAmount(tickerSummary.amount)}
                  </td>
                </tr>
              </tbody>
            </table>

            <table className="w-full border border-slate-200 text-sm text-slate-700">
              <thead className="bg-slate-50 text-slate-800">
                <tr>
                  <th className="border border-slate-200 px-3 py-2 text-left text-sm font-semibold text-slate-800">Class</th>
                  <th className="border border-slate-200 px-3 py-2 text-left text-sm font-semibold text-slate-800">Quantity</th>
                  <th className="border border-slate-200 px-3 py-2 text-right text-sm font-semibold text-slate-800">Total Amount</th>
                </tr>
              </thead>
              <tbody>
                {classSummary.map((item) => (
                  <tr key={`${item.label}-${item.quantity}-${item.amount}`}>
                    <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">{item.label}</td>
                    <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">{formatNumber(item.quantity)}</td>
                    <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-right text-slate-700">
                      {modalCurrency} {formatModalAmount(item.amount)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>

            <table className="w-full border border-slate-200 text-sm text-slate-700">
              <thead className="bg-slate-50 text-slate-800">
                <tr>
                  <th className="border border-slate-200 px-3 py-2 text-left text-sm font-semibold text-slate-800">Fees</th>
                  <th className="border border-slate-200 px-3 py-2 text-right text-sm font-semibold text-slate-800">Total Amount</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">Commission</td>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-right text-slate-700">{formatNumber(feeSummary.commission)}</td>
                </tr>
                <tr>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">Charges And Fees Abroad</td>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-right text-slate-700">{formatNumber(feeSummary.charges)}</td>
                </tr>
                <tr>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-slate-700">Federal Turnover Tax</td>
                  <td className="border border-slate-200 bg-slate-50/60 px-3 py-2 text-right text-slate-700">{formatNumber(feeSummary.tax)}</td>
                </tr>
              </tbody>
            </table>
          </div>

          <div className="flex justify-end border-t border-slate-100 bg-slate-50/60 px-4 py-4">
            <Button
              type="button"
              onClick={() => setShowSummaryModal(false)}
              className="bg-[#f0ad4e] text-white hover:bg-[#ec971f]"
            >
              Close
            </Button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
