"use client";

import { useEffect, useState } from "react";
import { GripVertical, Save } from "lucide-react";
import { createAllTransactionsColumns } from "@/components/datatable/alltransactions/page";
import { createStockColumns } from "@/components/datatable/liststock/columns";
import { createStructureColumns } from "@/components/datatable/liststructure/columns";
import { createBondColumns } from "@/components/datatable/listbond/columns";
import { createBondFundColumns } from "@/components/datatable/listbondfund/columns";
import { createCommodityColumns } from "@/components/datatable/listcommodity/columns";
import { createCommodityDerivativeColumns } from "@/components/datatable/listcommodityderivative/columns";
import { createOtherAssetColumns } from "@/components/datatable/listotherassets/columns";
import { createDepositColumns } from "@/components/datatable/listdeposits/columns";
import { createLeverageColumns } from "@/components/datatable/listleverage/columns";
import { createCashDerivativeColumns } from "@/components/datatable/listcashderivatives/columns";
import { createCurrencyConversionColumns } from "@/components/datatable/listcurrencyconversion/columns";
import { createCashWithdrawalColumns } from "@/components/datatable/listcashwithdrawal/columns";
import { createInterestDividendColumns } from "@/components/datatable/listinterestdividend/columns";

type Widget = {
  widget_id: string;
  name: string;
};

type ApiResponse = {
  status: string;
  data: Record<string, string>;
};

const widgetColumnFactories: Record<string, () => any[]> = {
  "All Transactions": createAllTransactionsColumns,
  "Stock": createStockColumns,
  "Equity Derivatives": createStockColumns,
  "Structure": createStructureColumns,
  "Bond": createBondColumns,
  "Bond Funds":createBondFundColumns,
  "Commodity": createCommodityColumns,
  "Commodity Derivatives": createCommodityDerivativeColumns,
  "Other Assets": createOtherAssetColumns,
  "Deposit": createDepositColumns,
  "Leverage": createLeverageColumns,
  "Cash Derivatives": createCashDerivativeColumns,
  "Currency Conversion": createCurrencyConversionColumns,
  "Cash Withdraw": createCashWithdrawalColumns,
  "Interest Dividend Transaction": createInterestDividendColumns,
};

const widgetReportIdMap: Record<string, number> = {
  "All Transactions": 1,
  "Stock": 2,
  "Equity Derivatives": 3,
  "Structure": 4,
  "Bond": 5,
  "Bond Funds": 6,
  "Commodity": 7,
  "Commodity Derivatives": 8,
  "Other Assets": 9,
  "Deposit": 10,
  "Leverage": 11,
  "Cash Derivatives": 12,
  "Currency Conversion": 13,
  "Cash Withdraw": 14,
  "Interest Dividend Transaction": 15,
};

export default function DashboardWidgetSettings() {
  const [available, setAvailable] = useState<Widget[]>([]);
  const [selected, setSelected] = useState<Widget[]>([]);
  const [currentWidget, setCurrentWidget] = useState<string | null>(null);
  const [showColumns, setShowColumns] = useState(false);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [saveError, setSaveError] = useState<string | null>(null);
  const [saveSuccess, setSaveSuccess] = useState<string | null>(null);
  const [widgetColumns, setWidgetColumns] = useState<Record<string, { id: string; label: string; visible: boolean }[]>>({});
  const [columnList, setColumnList] = useState<{ id: string; label: string; visible: boolean }[]>([]);
  const [dragColId, setDragColId] = useState<string | null>(null);

  useEffect(() => {
    const controller = new AbortController();
    const load = async () => {
      setLoading(true);
      setError(null);
      
      try {
        const res = await fetch("/api/settings/transaction", {
          method: "POST",
          credentials: "include",
          signal: controller.signal,
        });

        if (!res.ok) {
          const detail = await res.text();
          throw new Error(`Failed to load (${res.status}): ${detail}`);
        }

        const json = (await res.json()) as ApiResponse;
        const arr: Widget[] = Object.entries(json.data).map(([id, name]) => ({
          widget_id: id,
          name,
        }));
        
        
        setAvailable(arr);

        const defaultWidget = arr.find((w) => w.name === "All Transactions");
        if (defaultWidget) {
          handleSelectWidget(defaultWidget);
          setCurrentWidget(defaultWidget.name);
          setShowColumns(true);
        }
      } catch (err) {
        if ((err as Error).name === "AbortError") return;
        setError(err instanceof Error ? err.message : "Failed to load");
      } finally {
        setLoading(false);
      }
    };
    
    load();
    return () => controller.abort();
  }, []);

  const handleColDrop = (targetId: string) => {
    if (!dragColId || dragColId === targetId) return;

    const fromIndex = columnList.findIndex((c) => c.id === dragColId);
    const toIndex = columnList.findIndex((c) => c.id === targetId);
    if (fromIndex === -1 || toIndex === -1) return;

    const updated = [...columnList];
    const [moved] = updated.splice(fromIndex, 1);
    updated.splice(toIndex, 0, moved);

    setColumnList(updated);

    if (currentWidget) {
      setWidgetColumns((prev) => ({ ...prev, [currentWidget]: updated }));
    }

    setDragColId(null);
  };

  const toggleColumnVisibility = (id: string) => {
    const updated = columnList.map((c) =>
      c.id === id ? { ...c, visible: !c.visible } : c
    );

    setColumnList(updated);

    if (currentWidget) {
      setWidgetColumns((prev) => ({ ...prev, [currentWidget]: updated }));
    }
  };

  const handleSelectWidget = (widget: Widget) => {
    if (!selected.find((w) => w.widget_id === widget.widget_id)) {
      setSelected((prev) => [...prev, widget]);
    }

    setCurrentWidget(widget.name);

    const factory = widgetColumnFactories[widget.name];

    if (factory) {

      const existing = widgetColumns[widget.name];

      let cols =
        existing ??
        factory().map((col, idx) => {
          const id =
            col.id ??
            (typeof col.header === "string" ? col.header : `col-${idx}`);
          const label = typeof col.header === "string" ? col.header : id;
          return { id, label, visible: true };
        });

      setWidgetColumns((prev) => ({
        ...prev,
        [widget.name]: cols,
      }));

      setColumnList(cols);
      setShowColumns(true);
    } else {
      setShowColumns(false);
    }
  };

  const handleSaveColumns = async () => {
    if (!currentWidget) return;

    const reportId = widgetReportIdMap[currentWidget];
    const cols = widgetColumns[currentWidget];

    if (!reportId || !cols) return;

    const payload = cols.map((col, index) => ({
      report_id: reportId,
      column_name: col.id,
      priority: index + 1,
      visible: col.visible,
      essential: false,
    }));

    setSaving(true);
    setSaveError(null);
    setSaveSuccess(null);

    try {
      const res = await fetch("/api/settings/transaction/columns", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ columns: payload }),
      });

      if (!res.ok) {
        const detail = await res.text();
        throw new Error(`Save failed (${res.status}): ${detail}`);
      }

      setSaveSuccess("Column preferences saved!");
      setTimeout(() => setSaveSuccess(null), 2500);
    } catch (err) {
      setSaveError(
        err instanceof Error ? err.message : "Failed to save columns"
      );
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="container mx-auto px-4 py-10">
      <div className="rounded-lg border border-slate-200 bg-gradient-to-r from-indigo-50 via-white to-fuchsia-50 px-6 py-5 shadow-lg ring-1 ring-slate-100">
        <div className="flex justify-between">
          <div>
            <p className="text-[11px] tracking-[0.3em] uppercase text-indigo-700 font-semibold">
              Settings
            </p>
            <h1 className="text-2xl font-semibold text-slate-900">
              Transaction Priority Scheduling
            </h1>
            <p className="text-sm text-slate-600">
              Click a widget to view or configure details.
            </p>
          </div>

          <div className="flex items-center gap-2">

            <button
              type="button"
              onClick={handleSaveColumns}
              disabled={saving || loading || !!error}
              className="inline-flex items-center gap-2 rounded-lg border border-indigo-200 bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:-translate-y-0.5 hover:bg-indigo-500 disabled:opacity-60"
            >
              <Save className="h-4 w-4" />
              {saving ? "Saving…" : "Save order"}
            </button>
          </div>
        </div>
      </div>
      <div className="mt-6 grid gap-4 lg:grid-cols-[30%_70%]">
        <div className="rounded-lg border border-slate-200 bg-white shadow-lg">
          <div className="flex justify-between border-b px-5 py-3">
            <p className="text-[11px] uppercase tracking-[0.2em] text-slate-500 font-semibold">
              Available
            </p>
          </div>

          <div className="divide-y divide-slate-200">
            {available.map((widget) => (
              <div
                key={widget.widget_id}
                onClick={() => handleSelectWidget(widget)}
                className={`cursor-pointer px-5 py-3 text-sm hover:bg-indigo-50 ${
                  currentWidget === widget.name ? "bg-indigo-100" : ""
                }`}
              >
                <p className="font-semibold text-slate-900">{widget.name}</p>
              </div>
            ))}
          </div>
        </div>

        <div>
          {showColumns && currentWidget && (
            <div className="rounded-lg border border-slate-200 bg-white shadow-lg p-5 animate-fadeIn">
              <h2 className="text-xl font-semibold text-slate-900 mb-3">
                {currentWidget} – Columns
              </h2>

              <p className="text-xs text-slate-500 mb-4">
                Drag to reorder • Use checkbox to show/hide a column
              </p>

              <ul className="space-y-2 text-sm">
                {columnList.map((col) => (
                  <li
                    key={col.id}
                    draggable
                    onDragStart={() => setDragColId(col.id)}
                    onDragOver={(e) => e.preventDefault()}
                    onDrop={() => handleColDrop(col.id)}
                    className={`flex items-center justify-between gap-3 px-3 py-2 border rounded-lg bg-slate-50 cursor-move ${
                      dragColId === col.id ? "ring-2 ring-indigo-400" : ""
                    }`}
                  >
                    <div className="flex items-center gap-3">
                      <GripVertical className="h-4 w-4 text-slate-400" />
                      <span className="text-slate-800 font-medium">
                        {col.label}
                      </span>
                    </div>

                    <div className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        checked={col.visible}
                        onChange={() => toggleColumnVisibility(col.id)}
                        className="h-4 w-4"
                      />
                      <span className="text-xs text-slate-600">
                        {col.visible ? "Visible" : "Hidden"}
                      </span>
                    </div>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>
      </div>

      <style>{`
        @keyframes fadeIn {
          from { opacity: 0; transform: translateY(10px); }
          to { opacity: 1; transform: translateY(0); }
        }
        .animate-fadeIn {
          animation: fadeIn 0.25s ease-out;
        }
      `}</style>
    </div>
  );
}
