/**
 * `useSkills` — view-model hook for the skills feature (L12).
 *
 * Owns the skill lists for both scopes (`global` + `project`) of one project and
 * the CRUD actions. Consumes {@link SkillGateway} 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, Skill, SkillScope } from "@/domain";
import type { CreateSkillInput } from "@/ports";
import { useGateways } from "@/app/di";

/** What the skills UI needs from this hook. */
export interface SkillsViewModel {
  /** Global skills (reusable across projects). */
  globalSkills: Skill[];
  /** Project-scoped skills. */
  projectSkills: Skill[];
  /** Last error message, or `null`. */
  error: string | null;
  /** Whether a request is in flight. */
  busy: boolean;
  /** Reloads both scope lists. */
  refresh: () => Promise<void>;
  /** Creates a new skill and refreshes its scope's list. */
  createSkill: (input: Omit<CreateSkillInput, "projectId">) => Promise<void>;
  /** Updates the content of an existing skill. */
  updateSkill: (
    scope: SkillScope,
    skillId: string,
    content: string,
  ) => Promise<void>;
  /** Deletes a skill by id from its scope. */
  deleteSkill: (scope: SkillScope, skillId: string) => 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 useSkills(projectId: string): SkillsViewModel {
  const { skill } = useGateways();

  const [globalSkills, setGlobalSkills] = useState<Skill[]>([]);
  const [projectSkills, setProjectSkills] = useState<Skill[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const refresh = useCallback(async () => {
    if (!projectId) return;
    setBusy(true);
    setError(null);
    try {
      const [globals, projects] = await Promise.all([
        skill.listSkills(projectId, "global"),
        skill.listSkills(projectId, "project"),
      ]);
      setGlobalSkills(globals);
      setProjectSkills(projects);
    } catch (e) {
      setError(describe(e));
    } finally {
      setBusy(false);
    }
  }, [skill, projectId]);

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

  const setter = (scope: SkillScope) =>
    scope === "global" ? setGlobalSkills : setProjectSkills;

  const createSkill = useCallback(
    async (input: Omit<CreateSkillInput, "projectId">) => {
      setBusy(true);
      setError(null);
      try {
        const created = await skill.createSkill({ ...input, projectId });
        setter(input.scope)((prev) => [...prev, created]);
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [skill, projectId],
  );

  const updateSkill = useCallback(
    async (scope: SkillScope, skillId: string, content: string) => {
      setBusy(true);
      setError(null);
      try {
        const updated = await skill.updateSkill(
          projectId,
          scope,
          skillId,
          content,
        );
        setter(scope)((prev) =>
          prev.map((s) => (s.id === skillId ? updated : s)),
        );
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [skill, projectId],
  );

  const deleteSkill = useCallback(
    async (scope: SkillScope, skillId: string) => {
      setBusy(true);
      setError(null);
      try {
        await skill.deleteSkill(projectId, scope, skillId);
        setter(scope)((prev) => prev.filter((s) => s.id !== skillId));
      } catch (e) {
        setError(describe(e));
      } finally {
        setBusy(false);
      }
    },
    [skill, projectId],
  );

  return {
    globalSkills,
    projectSkills,
    error,
    busy,
    refresh,
    createSkill,
    updateSkill,
    deleteSkill,
  };
}
