import { useMemo } from 'react';
import { emit } from '@ablogcms/events';
import { Icon } from '@ablogcms/components/icon';
import { pending } from '@ablogcms/pending';
import { notify } from '@ablogcms/notify';
import type { Action } from '@ablogcms/components/dataview/types';
import { getDataviewActionRegistry } from '@ablogcms/plugins/core';
import { Tooltip } from '@ablogcms/components/tooltip';
import type { EntryType } from '../types';
import { createEntryEditLink } from '../utils';
import { duplicateEntry, trashEntry, unlockEntry } from '../api';

export interface GetActionsContext {
  invalidate: () => void;
}

export interface UseEntryAdminActionsOptions {
  getActions: (actions: Action<EntryType>[], context: GetActionsContext) => Action<EntryType>[];
  context: GetActionsContext;
}

export default function useEntryAdminActions({ getActions, context }: UseEntryAdminActionsOptions) {
  const actions = useMemo<Action<EntryType>[]>(() => {
    const actions: Action<EntryType>[] = [
      {
        id: 'edit',
        label: ACMS.i18n('entry_index.action.edit'),
        getHref: (data) => {
          return createEntryEditLink(data, 'entry_editor');
        },
        type: 'primary',
        linkProps: {
          className: 'acms-admin-btn-admin',
        },
        condition: (data) => data.actions.includes('edit'),
      },
      {
        id: 'approval-history',
        label: ACMS.i18n('entry_index.action.approval-history'),
        getHref: (data) => {
          return ACMS.Library.acmsLink({
            admin: 'entry_approval-history',
            eid: data.id,
          });
        },
        condition: (data) => data.actions.includes('approval-history'),
      },
      {
        id: 'duplicate',
        label: ACMS.i18n('entry_index.action.duplicate'),
        onAction: async (data) => {
          const end = pending.splash(ACMS.i18n('entry_index.action.feedback.duplicate.pending'));
          try {
            await duplicateEntry(data);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.action.feedback.duplicate.success'));
            void emit('entry.duplicate.success', { entry: data });
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.action.feedback.duplicate.error'));

            console.error(error);
          } finally {
            end();
          }
        },
        condition: (data) => data.actions.includes('duplicate'),
      },
      {
        id: 'trash',
        label: ACMS.i18n('entry_index.action.trash'),
        onAction: async (data) => {
          if (!window.confirm(ACMS.i18n('edit.message1'))) {
            return;
          }
          const gateResult = await emit('entry.trash.before', { entry: data });
          if (gateResult.canceled) {
            if (gateResult.reason) {
              notify.danger(gateResult.reason);
            }
            return;
          }
          const end = pending.splash(ACMS.i18n('entry_index.action.feedback.trash.pending'));
          try {
            // レジストリ境界で消去された行の型（RowData）を、元々渡した EntryType へ戻す
            // （dataview アクション/レジストリと同様のキャスト。events.ts の Why not 参照）
            await trashEntry(gateResult.event.entry as EntryType);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.action.feedback.trash.success'));
            void emit('entry.trash.success', gateResult.event);
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.action.feedback.trash.error'));

            console.error(error);
          } finally {
            end();
          }
        },
        condition: (data) => data.actions.includes('trash'),
      },
      {
        id: 'unlock',
        label: (
          <>
            <Icon name="lock_open" />
            <Tooltip id="entry-unlock-tooltip" />
          </>
        ),
        onAction: async (data) => {
          if (!window.confirm(ACMS.i18n('entry_index.action.feedback.unlock.confirm'))) {
            return;
          }
          const end = pending.splash(ACMS.i18n('entry_index.action.feedback.unlock.pending'));
          try {
            await unlockEntry(data);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.action.feedback.unlock.success', { title: data.title }));
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.action.feedback.unlock.error', { title: data.title }));

            console.error(error);
          } finally {
            end();
          }
        },
        type: 'tertiary',
        buttonProps: {
          className: 'acms-admin-btn-icon acms-admin-btn-unstyled',
          'data-tooltip-id': 'entry-unlock-tooltip',
          'data-tooltip-content': ACMS.i18n('entry_index.action.unlock'),
          'data-tooltip-place': 'top-start',
          'aria-label': ACMS.i18n('entry_index.action.unlock'),
        },
        // 自分が編集ロックしている場合のみ表示
        condition: (data) => data.lockUser != null && data.lockUser.id === parseInt(ACMS.Config.suid as string, 10),
      },
      {
        id: 'lock',
        label: (
          <>
            <Icon name="lock" />
            <Tooltip id="entry-lock-tooltip" />
          </>
        ),
        type: 'tertiary',
        buttonProps: (data) => ({
          className: 'acms-admin-btn-icon acms-admin-btn-unstyled',
          'data-tooltip-id': 'entry-lock-tooltip',
          'data-tooltip-content': ACMS.i18n('entry_index.action.lock', { name: data.lockUser?.name }),
          'data-tooltip-place': 'top-start',
          'aria-label': ACMS.i18n('entry_index.action.lock', { name: data.lockUser?.name }),
        }),
        // 自分以外のユーザーが編集ロックしている場合のみ表示
        condition: (data) => data.lockUser != null && data.lockUser.id !== parseInt(ACMS.Config.suid as string, 10),
      },
    ];
    // コア定義 → レジストリ（ctx.dataview.registerAction('entry', ...)） → レガシー getter の順にマージする
    // （design.md「レジストリ（機能登録）」節。既存 getter 利用者は combinedActions を受け取るだけで
    // 挙動は変わらない）。行の型はレジストリ境界で消去されている（`RowData` は実質 `unknown`）ため、
    // 既存の columnTypes と同様にここでキャストする。
    const registryActions = Object.values(getDataviewActionRegistry().getAll('entry')) as Action<EntryType>[];
    const combinedActions = [...actions, ...registryActions];
    return getActions(combinedActions, context);
  }, [context, getActions]);

  return actions;
}
