import { useMemo } from 'react';
import { emit } from '@ablogcms/events';
import UserSelect from '@features/user/components/user-select/user-select';
import CategorySelect from '@features/category/components/category-select/category-select';
import BlogSelect from '@features/blog/components/blog-select/blog-select';
import { isFetchError } from '@ablogcms/fetch-client';
import { notify } from '@ablogcms/notify';
import { pending } from '@ablogcms/pending';
import { Button } from '@ablogcms/components/button';
import { Select } from '@ablogcms/components/select';
import type { BulkAction } from '@ablogcms/components/dataview/types';
import { getDataviewBulkActionRegistry } from '@ablogcms/plugins/core';
import VisuallyHidden from '@ablogcms/components/visually-hidden';
import { HStack } from '@ablogcms/components/stack';
import type { EntrySort, EntrySortType, EntryType } from '../types';
import {
  bulkChangeBlog,
  bulkChangeCategory,
  bulkChangeStatus,
  bulkChangeUser,
  bulkDuplicate,
  bulkTrash,
  changeCategorySort,
  changeSort,
  changeUserSort,
  exportEntries,
} from '../api';
import { ENTRY_STATUSES } from '../constants';

export interface GetBulkActionsContext {
  invalidate: () => void;
  sort?: EntrySort;
  bulkActions: string[];
}

export interface UseEntryAdminBulkActionsOptions {
  getBulkActions: (bulkActions: BulkAction<EntryType>[], context: GetBulkActionsContext) => BulkAction<EntryType>[];
  context: GetBulkActionsContext;
}

export default function useEntryAdminBulkActions({ getBulkActions, context }: UseEntryAdminBulkActionsOptions) {
  const bulkActions = useMemo<BulkAction<EntryType>[]>(() => {
    const bulkActions: BulkAction<EntryType>[] = [
      {
        id: 'order',
        label: ACMS.i18n('entry_index.bulk_action.order'),
        onAction: async (formData: FormData) => {
          const intent = formData.get('intent') as EntrySortType | null;
          if (!intent) {
            return;
          }

          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.order.pending'));
          try {
            await {
              entry: changeSort,
              user: changeUserSort,
              category: changeCategorySort,
            }[intent](formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.order.success'));
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.order.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <Button
            type="submit"
            name="intent"
            value={context.sort?.type}
            unstyled
            className="acms-admin-btn-admin acms-admin-btn-admin-primary"
          >
            {ACMS.i18n('entry_index.bulk_change')}
          </Button>
        ),
        condition: () => context.bulkActions.includes('order'),
      },
      {
        id: 'status',
        label: ACMS.i18n('entry_index.bulk_action.status'),
        onAction: async (formData: FormData) => {
          const gateResult = await emit('entry.bulk-status.before', { formData });
          if (gateResult.canceled) {
            if (gateResult.reason) {
              notify.danger(gateResult.reason);
            }
            return;
          }
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.status.pending'));
          try {
            await bulkChangeStatus(gateResult.event.formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.status.success'));
            void emit('entry.bulk-status.success', gateResult.event);
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.status.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <>
            <label>
              <VisuallyHidden>{ACMS.i18n('entry_index.bulk_action.status')}</VisuallyHidden>
              <Select name="status">
                {ENTRY_STATUSES.map((status) => (
                  <option key={status.value} value={status.value}>
                    {status.label}
                  </option>
                ))}
              </Select>
            </label>
            <Button
              type="submit"
              name="ACMS_POST_Entry_Index_Status"
              unstyled
              className="acms-admin-btn-admin acms-admin-btn-admin-primary acms-admin-margin-left-mini"
            >
              {ACMS.i18n('entry_index.bulk_change')}
            </Button>
          </>
        ),
        condition: () => context.bulkActions.includes('status'),
      },
      {
        id: 'user',
        label: ACMS.i18n('entry_index.bulk_action.user'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.user.pending'));
          try {
            await bulkChangeUser(formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.user.success'));
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.user.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <HStack spacing="0.25rem">
            <label style={{ maxWidth: '100%', width: '220px' }}>
              <VisuallyHidden>{ACMS.i18n('entry_index.bulk_action.user')}</VisuallyHidden>
              <UserSelect name="uid" isClearable={false} />
            </label>
            <Button
              type="submit"
              name="ACMS_POST_Entry_Index_User"
              unstyled
              className="acms-admin-btn-admin acms-admin-btn-admin-primary acms-admin-margin-left-mini"
            >
              {ACMS.i18n('entry_index.bulk_change')}
            </Button>
          </HStack>
        ),
        condition: () => context.bulkActions.includes('user'),
      },
      {
        id: 'category',
        label: ACMS.i18n('entry_index.bulk_action.category'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.category.pending'));
          try {
            await bulkChangeCategory(formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.category.success'));
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.category.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <HStack spacing="0.25rem">
            <label style={{ maxWidth: '100%', width: '220px' }}>
              <VisuallyHidden>{ACMS.i18n('entry_index.bulk_action.category')}</VisuallyHidden>
              <CategorySelect name="cid" isClearable={false} />
            </label>
            <div>
              <Button
                type="submit"
                name="ACMS_POST_Entry_Index_Category"
                unstyled
                className="acms-admin-btn-admin acms-admin-btn-admin-primary"
              >
                {ACMS.i18n('entry_index.bulk_change')}
              </Button>
            </div>
          </HStack>
        ),
        condition: () => context.bulkActions.includes('category'),
      },
      {
        id: 'blog',
        label: ACMS.i18n('entry_index.bulk_action.blog'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.blog.pending'));
          try {
            await bulkChangeBlog(formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.blog.success'));
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.blog.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <div>
            <HStack spacing="0.25rem">
              <div style={{ maxWidth: '100%', width: '220px' }}>
                <BlogSelect name="bid" isClearable={false} scope="loggedInUserBlog" />
              </div>
              <div>
                <Button
                  type="submit"
                  name="ACMS_POST_Entry_Index_Blog"
                  unstyled
                  className="acms-admin-btn-admin acms-admin-btn-admin-primary acms-admin-margin-left-mini"
                >
                  {ACMS.i18n('entry_index.bulk_change')}
                </Button>
              </div>
            </HStack>
            <div>
              <span className="acms-admin-tab-text">{ACMS.i18n('entry_index.bulk_blog_note')}</span>
            </div>
          </div>
        ),
        condition: () => context.bulkActions.includes('blog'),
      },
      {
        id: 'duplicate',
        label: ACMS.i18n('entry_index.bulk_action.duplicate'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.duplicate.pending'));
          try {
            await bulkDuplicate(formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.duplicate.success'));
            void emit('entry.bulk-duplicate.success', { formData });
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.duplicate.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <div>
            <div>
              <Button
                type="submit"
                name="ACMS_POST_Entry_Index_Duplicate"
                unstyled
                className="acms-admin-btn-admin acms-admin-btn-admin-primary"
              >
                {ACMS.i18n('entry_index.exec')}
              </Button>
            </div>
            <div>
              <span className="acms-admin-tab-text">{ACMS.i18n('entry_index.bulk_duplicate_note')}</span>
            </div>
          </div>
        ),
        condition: () => context.bulkActions.includes('duplicate'),
      },
      {
        id: 'export',
        label: ACMS.i18n('entry_index.bulk_action.export'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.export.pending'));
          try {
            await exportEntries(formData);
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.export.success'));
          } catch (error) {
            if (isFetchError(error)) {
              notify.danger(error.message);
            } else {
              notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.export.error'));
            }
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <Button
            type="submit"
            name="ACMS_POST_Entry_Index_Export"
            unstyled
            className="acms-admin-btn-admin acms-admin-btn-admin-primary"
          >
            {ACMS.i18n('entry_index.exec')}
          </Button>
        ),
        condition: () => context.bulkActions.includes('export'),
      },
      {
        id: 'trash',
        label: ACMS.i18n('entry_index.bulk_action.trash'),
        onAction: async (formData: FormData) => {
          const end = pending.splash(ACMS.i18n('entry_index.bulk_action.feedback.trash.pending'));
          try {
            await bulkTrash(formData);
            context.invalidate();
            notify.info(ACMS.i18n('entry_index.bulk_action.feedback.trash.success'));
            void emit('entry.bulk-trash.success', { formData });
          } catch (error) {
            notify.danger(ACMS.i18n('entry_index.bulk_action.feedback.trash.error'));
            console.error(error);
          } finally {
            end();
          }
        },
        renderForm: () => (
          <Button
            type="submit"
            name="ACMS_POST_Entry_Index_Trash"
            unstyled
            className="acms-admin-btn-admin acms-admin-btn-admin-danger"
            onClick={() => window.confirm(ACMS.i18n('entry_index.bulk_action.feedback.trash.confirm'))}
          >
            {ACMS.i18n('entry_index.exec')}
          </Button>
        ),
        condition: () => context.bulkActions.includes('trash'),
      },
    ];
    // コア定義 → レジストリ（ctx.dataview.registerBulkAction('entry', ...)） → レガシー getter の順にマージする
    const registryBulkActions = Object.values(
      getDataviewBulkActionRegistry().getAll('entry')
    ) as BulkAction<EntryType>[];
    const combinedBulkActions = [...bulkActions, ...registryBulkActions];
    return getBulkActions(combinedBulkActions, context);
  }, [context, getBulkActions]);
  return bulkActions;
}
