/**
 * `useTemplates` — view-model hook for the templates feature (L7).
 *
 * Owns the templates list and CRUD actions. Consumes {@link TemplateGateway}
 * exclusively; never touches `invoke()` or `@tauri-apps/api`, keeping the
 * component layer testable with mock gateways (ARCHITECTURE §1.3).
 */

import { useCallback, useEffect, useState } from "react";

import type { GatewayError, Template } from "@/domain";
import type { CreateTemplateInput } from "@/ports";
import { useGateways } from "@/app/di";

/** What the templates UI needs from this hook. */
export interface TemplatesViewModel {
  /** All templates. */
  templates: Template[];
  /** Last error message, or `null`. */
  error: string | null;
  /** Whether a request is in flight. */
  busy: boolean;
  /** Reloads the template list. */
  refresh: () => Promise<void>;
  /** Creates a new template and refreshes the list. */
  createTemplate: (input: CreateTemplateInput) => Promise<void>;
  /** Updates the content of an existing template. */
  updateTemplate: (templateId: string, content: string) => Promise<void>;
  /** Deletes a template by id. */
  deleteTemplate: (templateId: string) => Promise<void>;
  /** Creates an agent from a template in the given project. */
  createAgentFromTemplate: (
    projectId: string,
    templateId: string,
    opts?: { name?: string; synchronized?: boolean },
  ) => Promise<void>;
}

function describe(e: unknown): string {
  if (e && typeof e === "object" && "message" in e) {
    return String((e as GatewayError).message);
  }
  return String(e);
}

export function useTemplates(): TemplatesViewModel {
  const { template } = useGateways();

  const [templates, setTemplates] = useState<Template[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const refresh = useCallback(async () => {
    setBusy(true);
    setError(null);
    try {
      const list = await template.listTemplates();
      setTemplates(list);
    } catch (e) {
      setError(describe(e));
    } finally {
      setBusy(false);
    }
  }, [template]);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const createTemplate = useCallback(
    async (input: CreateTemplateInput) => {
      setBusy(true);
      setError(null);
      try {
        const created = await template.createTemplate(input);
        setTemplates((prev) => [...prev, created]);
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [template],
  );

  const updateTemplate = useCallback(
    async (templateId: string, content: string) => {
      setBusy(true);
      setError(null);
      try {
        const updated = await template.updateTemplate(templateId, content);
        setTemplates((prev) =>
          prev.map((t) => (t.id === templateId ? updated : t)),
        );
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [template],
  );

  const deleteTemplate = useCallback(
    async (templateId: string) => {
      setBusy(true);
      setError(null);
      try {
        await template.deleteTemplate(templateId);
        setTemplates((prev) => prev.filter((t) => t.id !== templateId));
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [template],
  );

  const createAgentFromTemplate = useCallback(
    async (
      projectId: string,
      templateId: string,
      opts?: { name?: string; synchronized?: boolean },
    ) => {
      setBusy(true);
      setError(null);
      try {
        await template.createAgentFromTemplate(projectId, templateId, opts);
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [template],
  );

  return {
    templates,
    error,
    busy,
    refresh,
    createTemplate,
    updateTemplate,
    deleteTemplate,
    createAgentFromTemplate,
  };
}
