/**
 * 公告管理 Hooks
 *
 * contract §2.4：adminAnnouncements / createAnnouncement / publishAnnouncement / archiveAnnouncement / toggleAnnouncementPin
 */
import { useCallback, useState } from "react";
import { useGraphMutation, useGraphQuery } from "./use-graphql";
import {
  ADMIN_ANNOUNCEMENTS_QUERY,
  CREATE_ANNOUNCEMENT_MUTATION,
  PUBLISH_ANNOUNCEMENT_MUTATION,
  ARCHIVE_ANNOUNCEMENT_MUTATION,
  TOGGLE_ANNOUNCEMENT_PIN_MUTATION,
} from "@/lib/graphql-client";
import type {
  AnnouncementViewModel,
  PaginatedResult,
  ListFilter,
} from "@/types/view-models";

interface AdminAnnouncementsResponse {
  adminAnnouncements: PaginatedResult<AnnouncementViewModel>;
}

interface AnnouncementMutationResponse {
  createAnnouncement?: { id: string; title: string; status: string };
  publishAnnouncement?: { id: string; status: string };
  archiveAnnouncement?: { id: string; status: string };
  toggleAnnouncementPin?: { id: string; isPinned: boolean };
}

interface CreateAnnouncementInput {
  title: string;
  content: string;
  audience?: string[];
}

export function useAnnouncements(filter: Partial<ListFilter>) {
  const result = useGraphQuery<AdminAnnouncementsResponse>(
    ADMIN_ANNOUNCEMENTS_QUERY,
    { filter },
  );
  return {
    ...result,
    data: result.data?.adminAnnouncements ?? null,
  };
}

export function useAnnouncementFilter(initial?: Partial<ListFilter>) {
  const [filter, setFilter] = useState<Partial<ListFilter>>({
    page: 1,
    pageSize: 20,
    ...initial,
  });
  const setPage = useCallback(
    (page: number) => setFilter((f) => ({ ...f, page })),
    [],
  );
  const setSearch = useCallback(
    (search: string) => setFilter((f) => ({ ...f, search, page: 1 })),
    [],
  );
  const setStatus = useCallback(
    (status: string) => setFilter((f) => ({ ...f, status, page: 1 })),
    [],
  );
  return { filter, setFilter, setPage, setSearch, setStatus };
}

export function useCreateAnnouncement() {
  const [run, state] = useGraphMutation<
    AnnouncementMutationResponse,
    { input: CreateAnnouncementInput }
  >(CREATE_ANNOUNCEMENT_MUTATION);
  const create = useCallback(
    async (input: CreateAnnouncementInput) => {
      const res = await run({ input });
      return res.data?.createAnnouncement ?? null;
    },
    [run],
  );
  return [create, state] as const;
}

export function usePublishAnnouncement() {
  const [run, state] = useGraphMutation<
    AnnouncementMutationResponse,
    { id: string }
  >(PUBLISH_ANNOUNCEMENT_MUTATION);
  const publish = useCallback(
    async (id: string) => {
      const res = await run({ id });
      return res.data?.publishAnnouncement ?? null;
    },
    [run],
  );
  return [publish, state] as const;
}

export function useArchiveAnnouncement() {
  const [run, state] = useGraphMutation<
    AnnouncementMutationResponse,
    { id: string }
  >(ARCHIVE_ANNOUNCEMENT_MUTATION);
  const archive = useCallback(
    async (id: string) => {
      const res = await run({ id });
      return res.data?.archiveAnnouncement ?? null;
    },
    [run],
  );
  return [archive, state] as const;
}

export function useToggleAnnouncementPin() {
  const [run, state] = useGraphMutation<
    AnnouncementMutationResponse,
    { id: string }
  >(TOGGLE_ANNOUNCEMENT_PIN_MUTATION);
  const toggle = useCallback(
    async (id: string) => {
      const res = await run({ id });
      return res.data?.toggleAnnouncementPin ?? null;
    },
    [run],
  );
  return [toggle, state] as const;
}
