"use client";

import { useState, useEffect, useCallback, useMemo } from "react";
import { Plus, Pencil, Trash2, Server, FolderOpen } from "lucide-react";
import { useAppsContext } from "@/hooks/useAppsContext";
import type { AppEntry, AppHost, AppCategory } from "@/lib/types";
import { AppGrid } from "./AppGrid";
import { AppModal } from "./AppModal";
import { HostModal } from "./HostModal";
import { CategoryModal } from "./CategoryModal";
import { DeleteConfirmModal } from "./DeleteConfirmModal";

interface AppsViewProps {
  activeSubcategory: string;
}

function parseSubcategory(sub: string): { viewType: "host" | "type"; itemId: string } | null {
  if (sub.startsWith("by-host:")) {
    return { viewType: "host", itemId: sub.slice("by-host:".length) };
  }
  if (sub.startsWith("by-type:")) {
    return { viewType: "type", itemId: sub.slice("by-type:".length) };
  }
  return null;
}

export function AppsView({ activeSubcategory }: AppsViewProps) {
  const {
    hosts,
    categories,
    apps,
    loading,
    addHost,
    updateHost,
    deleteHost,
    addCategory,
    updateCategory,
    deleteCategory,
    addApp,
    updateApp,
    deleteApp,
    updateViewOrder,
    uploadIcon,
    refresh,
  } = useAppsContext();

  // Parse subcategory
  const parsed = parseSubcategory(activeSubcategory);
  const viewType = parsed?.viewType ?? null;
  const itemId = parsed?.itemId ?? null;
  const isAddMode = itemId === "add";

  // View order state
  const [viewOrder, setViewOrder] = useState<string[]>([]);

  // Modal state
  const [appModalOpen, setAppModalOpen] = useState(false);
  const [editingApp, setEditingApp] = useState<AppEntry | null>(null);
  const [hostModalOpen, setHostModalOpen] = useState(false);
  const [editingHost, setEditingHost] = useState<AppHost | null>(null);
  const [categoryModalOpen, setCategoryModalOpen] = useState(false);
  const [editingCategory, setEditingCategory] = useState<AppCategory | null>(null);
  const [deleteModalOpen, setDeleteModalOpen] = useState(false);
  const [deleteAffectedApps, setDeleteAffectedApps] = useState<AppEntry[]>([]);

  // Auto-open add modals when subcategory is "add"
  useEffect(() => {
    if (isAddMode && viewType === "host") {
      setEditingHost(null);
      setHostModalOpen(true);
    } else if (isAddMode && viewType === "type") {
      setEditingCategory(null);
      setCategoryModalOpen(true);
    }
  }, [isAddMode, viewType]);

  // Fetch view order when subcategory changes
  const viewKey = useMemo(() => {
    if (!itemId || isAddMode) return null;
    return viewType === "host" ? `host:${itemId}` : `category:${itemId}`;
  }, [viewType, itemId, isAddMode]);

  useEffect(() => {
    if (!viewKey) {
      setViewOrder([]);
      return;
    }
    fetch(`/api/apps/view-orders/${encodeURIComponent(viewKey)}`)
      .then((r) => r.json())
      .then((data) => setViewOrder(data.order ?? []))
      .catch(() => setViewOrder([]));
  }, [viewKey]);

  // Find the current host or category entity
  const currentHost = viewType === "host" && !isAddMode
    ? hosts.find((h) => h.id === itemId) ?? null
    : null;
  const currentCategory = viewType === "type" && !isAddMode
    ? categories.find((c) => c.id === itemId) ?? null
    : null;

  // Filter apps for the current view
  const filteredApps = useMemo(() => {
    if (!itemId || isAddMode) return [];
    if (viewType === "host") {
      return apps.filter((a) => a.hostId === itemId);
    }
    return apps.filter((a) => a.categoryId === itemId);
  }, [apps, viewType, itemId, isAddMode]);

  // Entity display info
  const entityName = currentHost
    ? currentHost.name
    : currentCategory
      ? currentCategory.name
      : "";
  const entitySubtitle = currentHost ? currentHost.address : currentCategory?.description ?? "";

  // Handlers
  const handleReorder = useCallback(
    (newOrder: string[]) => {
      setViewOrder(newOrder);
      if (viewKey) {
        updateViewOrder(viewKey, newOrder);
      }
    },
    [viewKey, updateViewOrder],
  );

  const handleEditApp = useCallback((app: AppEntry) => {
    setEditingApp(app);
    setAppModalOpen(true);
  }, []);

  const handleAppSave = useCallback(
    async (data: {
      name: string;
      url: string;
      hostId: string;
      categoryId: string;
      description?: string;
      icon: { type: string; value: string };
      color: string;
    }) => {
      if (editingApp) {
        await updateApp(editingApp.id, data);
      } else {
        await addApp(data as Parameters<typeof addApp>[0]);
      }
      setAppModalOpen(false);
      setEditingApp(null);
    },
    [editingApp, updateApp, addApp],
  );

  const handleAppDelete = useCallback(async () => {
    if (editingApp) {
      await deleteApp(editingApp.id);
      setAppModalOpen(false);
      setEditingApp(null);
    }
  }, [editingApp, deleteApp]);

  const handleHostSave = useCallback(
    async (data: { name: string; address: string; description?: string }) => {
      if (editingHost) {
        await updateHost(editingHost.id, data);
      } else {
        await addHost(data);
      }
      setHostModalOpen(false);
      setEditingHost(null);
    },
    [editingHost, updateHost, addHost],
  );

  const handleCategorySave = useCallback(
    async (data: { name: string; description?: string }) => {
      if (editingCategory) {
        await updateCategory(editingCategory.id, data);
      } else {
        await addCategory(data);
      }
      setCategoryModalOpen(false);
      setEditingCategory(null);
    },
    [editingCategory, updateCategory, addCategory],
  );

  const handleDeleteEntity = useCallback(async () => {
    if (!itemId || isAddMode) return;

    if (viewType === "host") {
      const result = await deleteHost(itemId);
      if (!result.deleted && result.affectedApps) {
        setDeleteAffectedApps(result.affectedApps);
        setDeleteModalOpen(true);
      }
    } else {
      const result = await deleteCategory(itemId);
      if (!result.deleted && result.affectedApps) {
        setDeleteAffectedApps(result.affectedApps);
        setDeleteModalOpen(true);
      }
    }
  }, [viewType, itemId, isAddMode, deleteHost, deleteCategory]);

  const handleCascadeDelete = useCallback(async () => {
    if (!itemId || isAddMode) return;
    if (viewType === "host") {
      await deleteHost(itemId, true);
    } else {
      await deleteCategory(itemId, true);
    }
    setDeleteModalOpen(false);
    setDeleteAffectedApps([]);
  }, [viewType, itemId, isAddMode, deleteHost, deleteCategory]);

  const handleReassign = useCallback(
    async (newId: string) => {
      if (!itemId || isAddMode) return;
      // Reassign each affected app to the new host/category, then delete the entity with cascade
      for (const app of deleteAffectedApps) {
        if (viewType === "host") {
          await updateApp(app.id, { hostId: newId });
        } else {
          await updateApp(app.id, { categoryId: newId });
        }
      }
      // Now delete the entity (no apps reference it anymore)
      if (viewType === "host") {
        await deleteHost(itemId, true);
      } else {
        await deleteCategory(itemId, true);
      }
      setDeleteModalOpen(false);
      setDeleteAffectedApps([]);
    },
    [viewType, itemId, isAddMode, deleteAffectedApps, updateApp, deleteHost, deleteCategory],
  );

  // Alternatives for delete reassign (all other hosts or categories except the current one)
  const deleteAlternatives = useMemo(() => {
    if (viewType === "host") {
      return hosts
        .filter((h) => h.id !== itemId)
        .map((h) => ({ id: h.id, name: h.name }));
    }
    return categories
      .filter((c) => c.id !== itemId)
      .map((c) => ({ id: c.id, name: c.name }));
  }, [viewType, itemId, hosts, categories]);

  // Loading state
  if (loading) {
    return (
      <div className="flex flex-1 items-center justify-center">
        <p className="text-sm text-zinc-400 dark:text-zinc-500">Loading apps...</p>
      </div>
    );
  }

  // Add mode just shows the modal, no grid
  if (isAddMode) {
    return (
      <>
        <div className="flex flex-1 items-center justify-center">
          <p className="text-sm text-zinc-400 dark:text-zinc-500">
            {viewType === "host" ? "Adding a new host..." : "Adding a new category..."}
          </p>
        </div>
        <HostModal
          open={hostModalOpen && viewType === "host"}
          onClose={() => setHostModalOpen(false)}
          onSave={handleHostSave}
        />
        <CategoryModal
          open={categoryModalOpen && viewType === "type"}
          onClose={() => setCategoryModalOpen(false)}
          onSave={handleCategorySave}
        />
      </>
    );
  }

  // Entity not found
  if (!currentHost && !currentCategory) {
    return (
      <div className="flex flex-1 items-center justify-center">
        <p className="text-sm text-zinc-400 dark:text-zinc-500">
          {viewType === "host" ? "Host" : "Category"} not found.
        </p>
      </div>
    );
  }

  return (
    <div className="flex flex-1 flex-col overflow-hidden">
      {/* Top bar */}
      <div className="flex items-center justify-between border-b border-zinc-200 px-3 py-3 md:px-6 md:py-4 dark:border-zinc-800">
        <div className="flex min-w-0 items-center gap-2 md:gap-3">
          {viewType === "host" ? (
            <Server size={20} className="shrink-0 text-zinc-400" />
          ) : (
            <FolderOpen size={20} className="shrink-0 text-zinc-400" />
          )}
          <div className="min-w-0">
            <h2 className="truncate text-base font-semibold text-zinc-900 md:text-lg dark:text-zinc-100">
              {entityName}
            </h2>
            {entitySubtitle && (
              <p className="truncate text-sm text-zinc-500 dark:text-zinc-400">
                {entitySubtitle}
              </p>
            )}
          </div>
        </div>
        <div className="flex shrink-0 items-center gap-1 md:gap-2">
          <button
            onClick={() => {
              setEditingApp(null);
              setAppModalOpen(true);
            }}
            className="flex items-center gap-1.5 rounded-lg bg-blue-600 px-2.5 py-2 text-sm font-medium text-white hover:bg-blue-700 md:px-3"
          >
            <Plus size={16} />
            <span className="hidden sm:inline">Add App</span>
          </button>
          <button
            onClick={() => {
              if (viewType === "host" && currentHost) {
                setEditingHost(currentHost);
                setHostModalOpen(true);
              } else if (currentCategory) {
                setEditingCategory(currentCategory);
                setCategoryModalOpen(true);
              }
            }}
            className="flex items-center gap-1.5 rounded-lg px-2.5 py-2 text-sm text-zinc-600 hover:bg-zinc-100 md:px-3 dark:text-zinc-400 dark:hover:bg-zinc-800"
          >
            <Pencil size={14} />
            <span className="hidden sm:inline">Edit</span>
          </button>
          <button
            onClick={handleDeleteEntity}
            className="flex items-center gap-1.5 rounded-lg px-2.5 py-2 text-sm text-red-500 hover:bg-red-50 md:px-3 dark:hover:bg-red-950/30"
          >
            <Trash2 size={14} />
            <span className="hidden sm:inline">Delete</span>
          </button>
        </div>
      </div>

      {/* App grid or empty state */}
      {filteredApps.length === 0 ? (
        <div className="flex flex-1 items-center justify-center">
          <div className="flex flex-col items-center gap-3 text-center">
            <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-100 dark:bg-zinc-800">
              {viewType === "host" ? (
                <Server size={24} className="text-zinc-400" />
              ) : (
                <FolderOpen size={24} className="text-zinc-400" />
              )}
            </div>
            <div>
              <p className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                No apps yet
              </p>
              <p className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">
                Add your first app to {entityName}.
              </p>
            </div>
            <button
              onClick={() => {
                setEditingApp(null);
                setAppModalOpen(true);
              }}
              className="flex items-center gap-1.5 rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700"
            >
              <Plus size={16} />
              Add App
            </button>
          </div>
        </div>
      ) : (
        <div className="flex-1 overflow-y-auto">
          <AppGrid
            apps={filteredApps}
            order={viewOrder}
            categories={categories}
            onEditApp={handleEditApp}
            onReorder={handleReorder}
          />
        </div>
      )}

      {/* Modals */}
      <AppModal
        open={appModalOpen}
        onClose={() => {
          setAppModalOpen(false);
          setEditingApp(null);
        }}
        onSave={handleAppSave}
        onDelete={editingApp ? handleAppDelete : undefined}
        editApp={editingApp}
        hosts={hosts}
        categories={categories}
        defaultHostId={viewType === "host" ? itemId ?? undefined : undefined}
        defaultCategoryId={viewType === "type" ? itemId ?? undefined : undefined}
        onUploadIcon={uploadIcon}
        onAddHost={addHost}
        onAddCategory={addCategory}
      />
      <HostModal
        open={hostModalOpen}
        onClose={() => {
          setHostModalOpen(false);
          setEditingHost(null);
        }}
        onSave={handleHostSave}
        editHost={editingHost}
      />
      <CategoryModal
        open={categoryModalOpen}
        onClose={() => {
          setCategoryModalOpen(false);
          setEditingCategory(null);
        }}
        onSave={handleCategorySave}
        editCategory={editingCategory}
      />
      <DeleteConfirmModal
        open={deleteModalOpen}
        onClose={() => {
          setDeleteModalOpen(false);
          setDeleteAffectedApps([]);
        }}
        entityType={viewType === "host" ? "host" : "category"}
        entityName={entityName}
        affectedApps={deleteAffectedApps}
        alternatives={deleteAlternatives}
        onCascade={handleCascadeDelete}
        onReassign={handleReassign}
      />
    </div>
  );
}
