import React, { useState, useMemo, useCallback } from "react";
import { createRoot } from "react-dom/client";
import { useApp, useHostStyles } from "@modelcontextprotocol/ext-apps/react";

// ─── Types ─────────────────────────────────────────────
interface WorkflowNode {
  id: string;
  name: string;
  type: string;
  position: [number, number];
  parameters?: Record<string, unknown>;
}

interface WorkflowTag {
  id: string;
  name: string;
}

interface Workflow {
  id: string;
  name: string;
  active: boolean;
  createdAt: string;
  updatedAt: string;
  nodes: WorkflowNode[];
  tags: WorkflowTag[];
}

type FilterMode = "all" | "active" | "inactive";

interface ToastState {
  message: string;
  type: "success" | "error";
}

interface ConfirmState {
  workflowId: string;
  workflowName: string;
}

// ─── Helpers ───────────────────────────────────────────
function timeAgo(dateStr: string): string {
  const now = Date.now();
  const then = new Date(dateStr).getTime();
  const diffMs = now - then;
  const mins = Math.floor(diffMs / 60000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  const days = Math.floor(hrs / 24);
  if (days < 30) return `${days}d ago`;
  const months = Math.floor(days / 30);
  return `${months}mo ago`;
}

function shortNodeType(type: string): string {
  return type
    .replace(/^n8n-nodes-base\./, "")
    .replace(/^@n8n\/n8n-nodes-langchain\./, "")
    .replace(/Trigger$/, " ⚡")
    .replace(/([A-Z])/g, " $1")
    .trim();
}

function isTriggerNode(type: string): boolean {
  return type.toLowerCase().includes("trigger") || type.toLowerCase().includes("webhook");
}

// ─── Stat Card Component ───────────────────────────────
function StatCard({ value, label, variant }: { value: number | string; label: string; variant?: string }) {
  return (
    <div className={`stat-card ${variant || ""}`}>
      <div className="stat-value">{value}</div>
      <div className="stat-label">{label}</div>
    </div>
  );
}

// ─── Flow Preview Component ────────────────────────────
function FlowPreview({ nodes }: { nodes: WorkflowNode[] }) {
  const maxShow = 5;
  const displayed = nodes.slice(0, maxShow);
  const remaining = nodes.length - maxShow;

  if (nodes.length === 0) {
    return <div style={{ fontSize: 12, color: "var(--color-text-dim)", padding: "8px 0" }}>No nodes</div>;
  }

  return (
    <div className="flow-preview">
      <div className="flow-container">
        {displayed.map((node, i) => (
          <React.Fragment key={node.id || i}>
            {i > 0 && <span className="flow-arrow">→</span>}
            <span className={`flow-node ${isTriggerNode(node.type) ? "trigger" : ""}`}>
              {shortNodeType(node.type)}
            </span>
          </React.Fragment>
        ))}
        {remaining > 0 && (
          <>
            <span className="flow-arrow">→</span>
            <span className="flow-node" style={{ opacity: 0.6 }}>+{remaining} more</span>
          </>
        )}
      </div>
    </div>
  );
}

// ─── Confirm Dialog Component ──────────────────────────
function ConfirmDialog({
  workflow,
  onConfirm,
  onCancel,
  loading,
}: {
  workflow: ConfirmState;
  onConfirm: () => void;
  onCancel: () => void;
  loading: boolean;
}) {
  return (
    <div className="confirm-overlay" onClick={onCancel}>
      <div className="confirm-dialog" onClick={(e) => e.stopPropagation()}>
        <h3>🗑️ Delete Workflow</h3>
        <p>
          Are you sure you want to delete <strong>"{workflow.workflowName}"</strong>? This action cannot be undone.
        </p>
        <div className="actions">
          <button className="btn btn-secondary btn-sm" onClick={onCancel} disabled={loading}>
            Cancel
          </button>
          <button className="btn btn-danger btn-sm" onClick={onConfirm} disabled={loading}>
            {loading ? <><span className="spinner" style={{ width: 14, height: 14 }} /> Deleting...</> : "Delete"}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Toast Component ───────────────────────────────────
function Toast({ toast, onDismiss }: { toast: ToastState; onDismiss: () => void }) {
  React.useEffect(() => {
    const timer = setTimeout(onDismiss, 3500);
    return () => clearTimeout(timer);
  }, [onDismiss]);

  return (
    <div className={`toast ${toast.type}`} onClick={onDismiss}>
      {toast.type === "success" ? "✓" : "✗"} {toast.message}
    </div>
  );
}

// ─── Workflow Card Component ───────────────────────────
function WorkflowCard({
  workflow,
  onToggle,
  onDelete,
  onClick,
  hasServerTools,
}: {
  workflow: Workflow;
  onToggle: (id: string, active: boolean) => void;
  onDelete: (id: string, name: string) => void;
  onClick: (id: string) => void;
  hasServerTools: boolean;
}) {
  const [toggling, setToggling] = useState(false);

  const handleToggle = async (e: React.MouseEvent) => {
    e.stopPropagation();
    setToggling(true);
    await onToggle(workflow.id, !workflow.active);
    setToggling(false);
  };

  const handleDelete = (e: React.MouseEvent) => {
    e.stopPropagation();
    onDelete(workflow.id, workflow.name);
  };

  return (
    <div className="card workflow-card" onClick={() => onClick(workflow.id)}>
      <div className="card-header">
        <span className="workflow-name" title={workflow.name}>
          {workflow.name}
        </span>
        <span className={`badge ${workflow.active ? "active" : "inactive"}`}>
          {workflow.active ? "● Active" : "○ Inactive"}
        </span>
      </div>
      <div className="card-body" style={{ paddingTop: 12, paddingBottom: 12 }}>
        <FlowPreview nodes={workflow.nodes || []} />
        <div className="workflow-meta">
          <span>🔧 {(workflow.nodes || []).length} nodes</span>
          <span>🕐 {timeAgo(workflow.updatedAt)}</span>
          {workflow.tags?.length > 0 && (
            <span>🏷️ {workflow.tags.map((t) => t.name).join(", ")}</span>
          )}
        </div>
      </div>
      {hasServerTools && (
        <div className="card-footer">
          <button
            className={`btn btn-sm ${workflow.active ? "btn-secondary" : "btn-primary"}`}
            onClick={handleToggle}
            disabled={toggling}
            title={workflow.active ? "Deactivate workflow" : "Activate workflow"}
          >
            {toggling ? (
              <span className="spinner" style={{ width: 12, height: 12 }} />
            ) : workflow.active ? (
              "⏸ Deactivate"
            ) : (
              "▶ Activate"
            )}
          </button>
          <button className="btn btn-danger btn-sm" onClick={handleDelete} title="Delete workflow">
            🗑️
          </button>
        </div>
      )}
    </div>
  );
}

// ─── Main Dashboard Component ──────────────────────────
function WorkflowDashboard() {
  const [workflows, setWorkflows] = useState<Workflow[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState("");
  const [filter, setFilter] = useState<FilterMode>("all");
  const [toast, setToast] = useState<ToastState | null>(null);
  const [confirmDelete, setConfirmDelete] = useState<ConfirmState | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [serverToolsAvailable, setServerToolsAvailable] = useState(false);

  const { app, isConnected, error } = useApp({
    appInfo: { name: "n8n-workflow-dashboard", version: "1.0.0" },
    capabilities: {},
    onAppCreated: (app) => {
      app.ontoolresult = (params: any) => {
        if (params.isError) {
          setLoading(false);
          return;
        }
        try {
          const textContent = params.content?.find(
            (c: { type: string }) => c.type === "text"
          ) as { type: "text"; text: string } | undefined;
          if (textContent?.text) {
            const parsed = JSON.parse(textContent.text);
            if (Array.isArray(parsed?.data)) {
              setWorkflows(parsed.data);
            } else if (Array.isArray(parsed)) {
              setWorkflows(parsed);
            }
          }
        } catch (err) {
          console.error("Failed to parse workflow data:", err);
        }
        setLoading(false);
      };

      app.ontoolinput = () => {
        setLoading(true);
      };
    },
  });

  useHostStyles(app, app?.getHostContext());

  // Check capabilities once connected
  React.useEffect(() => {
    if (app && isConnected) {
      try {
        const caps = app.getHostCapabilities();
        setServerToolsAvailable(!!caps?.serverTools);
      } catch {
        setServerToolsAvailable(false);
      }
    }
  }, [app, isConnected]);

  // Filter + search
  const filtered = useMemo(() => {
    let result = [...workflows];

    if (filter === "active") result = result.filter((w) => w.active);
    else if (filter === "inactive") result = result.filter((w) => !w.active);

    if (search.trim()) {
      const q = search.toLowerCase();
      result = result.filter(
        (w) =>
          w.name.toLowerCase().includes(q) ||
          w.tags?.some((t) => t.name.toLowerCase().includes(q)) ||
          w.nodes?.some((n) => n.type.toLowerCase().includes(q) || n.name.toLowerCase().includes(q))
      );
    }

    return result.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
  }, [workflows, filter, search]);

  // Stats
  const stats = useMemo(() => {
    const total = workflows.length;
    const active = workflows.filter((w) => w.active).length;
    const inactive = total - active;
    const totalNodes = workflows.reduce((sum, w) => sum + (w.nodes?.length || 0), 0);
    return { total, active, inactive, totalNodes };
  }, [workflows]);

  // Handlers
  const showToast = useCallback((message: string, type: "success" | "error") => {
    setToast({ message, type });
  }, []);

  const handleToggle = useCallback(
    async (id: string, newActive: boolean) => {
      if (!app || !serverToolsAvailable) {
        showToast("Server tools not available", "error");
        return;
      }
      try {
        const result = await app.callServerTool({
          name: "n8n_toggle_workflow",
          arguments: { id, active: newActive },
        });
        if (!result.isError) {
          setWorkflows((prev) => prev.map((w) => (w.id === id ? { ...w, active: newActive } : w)));
          showToast(`Workflow ${newActive ? "activated" : "deactivated"}`, "success");
        } else {
          showToast("Toggle failed", "error");
        }
      } catch (err: any) {
        showToast(err.message || "Toggle failed", "error");
      }
    },
    [app, serverToolsAvailable, showToast]
  );

  const handleDeleteConfirm = useCallback(async () => {
    if (!confirmDelete || !app || !serverToolsAvailable) return;
    setDeleting(true);
    try {
      const result = await app.callServerTool({
        name: "n8n_delete_workflow_action",
        arguments: { id: confirmDelete.workflowId },
      });
      if (!result.isError) {
        setWorkflows((prev) => prev.filter((w) => w.id !== confirmDelete.workflowId));
        showToast(`"${confirmDelete.workflowName}" deleted`, "success");
        setConfirmDelete(null);
      } else {
        showToast("Delete failed", "error");
      }
    } catch (err: any) {
      showToast(err.message || "Delete failed", "error");
    }
    setDeleting(false);
  }, [app, confirmDelete, serverToolsAvailable, showToast]);

  const handleCardClick = useCallback(
    (id: string) => {
      if (!app) return;
      try {
        app.sendMessage({ text: `Show workflow detail for ${id}` });
      } catch {
        // fallback: no-op if sendMessage not supported
      }
    },
    [app]
  );

  // ─── Render ────────────────────────────────────────
  if (error) {
    return (
      <div className="page">
        <div className="empty-state">
          <div className="icon">⚠️</div>
          <h3>Connection Error</h3>
          <p>{error.message}</p>
        </div>
      </div>
    );
  }

  if (!isConnected || loading) {
    return (
      <div className="page">
        <div className="loading-container">
          <div className="spinner" />
          <p>Loading workflows...</p>
        </div>
      </div>
    );
  }

  return (
    <div className="page">
      {/* Header */}
      <div className="page-header">
        <div>
          <div className="page-title">
            <span className="icon">⚡</span>
            Workflow Dashboard
          </div>
          <div className="page-subtitle">Manage and monitor your n8n workflows</div>
        </div>
      </div>

      {/* Stats */}
      <div className="stats-row">
        <StatCard value={stats.total} label="Total Workflows" variant="accent" />
        <StatCard value={stats.active} label="Active" variant="success" />
        <StatCard value={stats.inactive} label="Inactive" variant="warning" />
        <StatCard value={stats.totalNodes} label="Total Nodes" />
      </div>

      {/* Filter Bar */}
      <div className="filter-bar">
        <div className="search-box">
          <span className="search-icon">🔍</span>
          <input
            className="input"
            type="text"
            placeholder="Search workflows, nodes, tags..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <div className="filter-toggles">
          {(["all", "active", "inactive"] as FilterMode[]).map((mode) => (
            <button
              key={mode}
              className={`filter-toggle ${filter === mode ? "active" : ""}`}
              onClick={() => setFilter(mode)}
            >
              {mode === "all" ? "All" : mode === "active" ? "Active" : "Inactive"}
              {mode === "all"
                ? ` (${stats.total})`
                : mode === "active"
                ? ` (${stats.active})`
                : ` (${stats.inactive})`}
            </button>
          ))}
        </div>
      </div>

      {/* Workflow Grid */}
      {filtered.length === 0 ? (
        <div className="empty-state">
          <div className="icon">📋</div>
          <h3>{search || filter !== "all" ? "No matching workflows" : "No workflows found"}</h3>
          <p>
            {search || filter !== "all"
              ? "Try adjusting your search or filter criteria."
              : "Create your first workflow in n8n to see it here."}
          </p>
        </div>
      ) : (
        <div className="grid grid-2">
          {filtered.map((wf) => (
            <WorkflowCard
              key={wf.id}
              workflow={wf}
              onToggle={handleToggle}
              onDelete={(id, name) => setConfirmDelete({ workflowId: id, workflowName: name })}
              onClick={handleCardClick}
              hasServerTools={serverToolsAvailable}
            />
          ))}
        </div>
      )}

      {/* Confirm Dialog */}
      {confirmDelete && (
        <ConfirmDialog
          workflow={confirmDelete}
          onConfirm={handleDeleteConfirm}
          onCancel={() => setConfirmDelete(null)}
          loading={deleting}
        />
      )}

      {/* Toast */}
      {toast && <Toast toast={toast} onDismiss={() => setToast(null)} />}
    </div>
  );
}

// ─── Mount ─────────────────────────────────────────────
const root = createRoot(document.getElementById("root")!);
root.render(<WorkflowDashboard />);
