"use client";

import { useState, useEffect, useCallback } from "react";
import type { AppHost, AppCategory, AppEntry } from "@/lib/types";

export interface UseAppsReturn {
  hosts: AppHost[];
  categories: AppCategory[];
  apps: AppEntry[];
  loading: boolean;
  error: string | null;
  // Hosts
  addHost: (data: { name: string; address: string; description?: string }) => Promise<AppHost>;
  updateHost: (id: string, updates: { name?: string; address?: string; description?: string }) => Promise<void>;
  deleteHost: (id: string, cascade?: boolean) => Promise<{ deleted: boolean; affectedApps?: AppEntry[] }>;
  // Categories
  addCategory: (data: { name: string; description?: string }) => Promise<AppCategory>;
  updateCategory: (id: string, updates: { name?: string; description?: string }) => Promise<void>;
  deleteCategory: (id: string, cascade?: boolean) => Promise<{ deleted: boolean; affectedApps?: AppEntry[] }>;
  // Apps
  addApp: (data: { name: string; url: string; hostId: string; categoryId: string; description?: string; icon?: { type: string; value: string }; color?: string }) => Promise<AppEntry>;
  updateApp: (id: string, updates: Record<string, unknown>) => Promise<void>;
  deleteApp: (id: string) => Promise<void>;
  // View Orders
  updateViewOrder: (viewKey: string, order: string[]) => Promise<void>;
  // Upload
  uploadIcon: (file: File) => Promise<string>;
  // Refresh
  refresh: () => void;
}

export function useApps(): UseAppsReturn {
  const [hosts, setHosts] = useState<AppHost[]>([]);
  const [categories, setCategories] = useState<AppCategory[]>([]);
  const [apps, setApps] = useState<AppEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [refreshKey, setRefreshKey] = useState(0);

  const refresh = useCallback(() => setRefreshKey((k) => k + 1), []);

  useEffect(() => {
    setLoading(true);
    Promise.all([
      fetch("/api/apps/hosts").then(r => r.json()),
      fetch("/api/apps/categories").then(r => r.json()),
      fetch("/api/apps/entries").then(r => r.json()),
    ])
      .then(([hostsData, catsData, appsData]) => {
        setHosts(hostsData.hosts);
        setCategories(catsData.categories);
        setApps(appsData.apps);
        setError(null);
      })
      .catch((err) => setError(err.message))
      .finally(() => setLoading(false));
  }, [refreshKey]);

  const addHostFn = useCallback(async (data: { name: string; address: string; description?: string }) => {
    const resp = await fetch("/api/apps/hosts", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    const result = await resp.json();
    refresh();
    return result.host as AppHost;
  }, [refresh]);

  const updateHostFn = useCallback(async (id: string, updates: { name?: string; address?: string; description?: string }) => {
    const resp = await fetch(`/api/apps/hosts/${encodeURIComponent(id)}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(updates),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    refresh();
  }, [refresh]);

  const deleteHostFn = useCallback(async (id: string, cascade?: boolean) => {
    const url = cascade ? `/api/apps/hosts/${encodeURIComponent(id)}?cascade=true` : `/api/apps/hosts/${encodeURIComponent(id)}`;
    const resp = await fetch(url, { method: "DELETE" });
    const data = await resp.json();
    if (resp.status === 409) return { deleted: false, affectedApps: data.affectedApps as AppEntry[] };
    if (!resp.ok) throw new Error(data.error);
    refresh();
    return { deleted: true };
  }, [refresh]);

  const addCategoryFn = useCallback(async (data: { name: string; description?: string }) => {
    const resp = await fetch("/api/apps/categories", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    const result = await resp.json();
    refresh();
    return result.category as AppCategory;
  }, [refresh]);

  const updateCategoryFn = useCallback(async (id: string, updates: { name?: string; description?: string }) => {
    const resp = await fetch(`/api/apps/categories/${encodeURIComponent(id)}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(updates),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    refresh();
  }, [refresh]);

  const deleteCategoryFn = useCallback(async (id: string, cascade?: boolean) => {
    const url = cascade ? `/api/apps/categories/${encodeURIComponent(id)}?cascade=true` : `/api/apps/categories/${encodeURIComponent(id)}`;
    const resp = await fetch(url, { method: "DELETE" });
    const data = await resp.json();
    if (resp.status === 409) return { deleted: false, affectedApps: data.affectedApps as AppEntry[] };
    if (!resp.ok) throw new Error(data.error);
    refresh();
    return { deleted: true };
  }, [refresh]);

  const addAppFn = useCallback(async (data: { name: string; url: string; hostId: string; categoryId: string; description?: string; icon?: { type: string; value: string }; color?: string }) => {
    const resp = await fetch("/api/apps/entries", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    const result = await resp.json();
    refresh();
    return result.app as AppEntry;
  }, [refresh]);

  const updateAppFn = useCallback(async (id: string, updates: Record<string, unknown>) => {
    const resp = await fetch(`/api/apps/entries/${encodeURIComponent(id)}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(updates),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    refresh();
  }, [refresh]);

  const deleteAppFn = useCallback(async (id: string) => {
    const resp = await fetch(`/api/apps/entries/${encodeURIComponent(id)}`, { method: "DELETE" });
    if (!resp.ok) throw new Error((await resp.json()).error);
    refresh();
  }, [refresh]);

  const updateViewOrderFn = useCallback(async (viewKey: string, order: string[]) => {
    const resp = await fetch(`/api/apps/view-orders/${encodeURIComponent(viewKey)}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ order }),
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    refresh();
  }, [refresh]);

  const uploadIconFn = useCallback(async (file: File) => {
    const formData = new FormData();
    formData.append("icon", file);
    const resp = await fetch("/api/apps/upload-icon", {
      method: "POST",
      body: formData,
    });
    if (!resp.ok) throw new Error((await resp.json()).error);
    const result = await resp.json();
    return result.url as string;
  }, []);

  return {
    hosts, categories, apps, loading, error,
    addHost: addHostFn, updateHost: updateHostFn, deleteHost: deleteHostFn,
    addCategory: addCategoryFn, updateCategory: updateCategoryFn, deleteCategory: deleteCategoryFn,
    addApp: addAppFn, updateApp: updateAppFn, deleteApp: deleteAppFn,
    updateViewOrder: updateViewOrderFn,
    uploadIcon: uploadIconFn,
    refresh,
  };
}
