'use client';

import React, { ReactNode, useRef } from 'react';
import Link from 'next/link';
import { X } from 'lucide-react';
import { Modal, Button, Tooltip, Typography, Spin } from 'antd';
import {
    mergeWaygestFormModalBodyStyles,
    useWaygestFormModalProps,
} from '@/hooks/useWaygestFormModalProps';
import { useResponsiveModalProps } from '@/hooks/useResponsiveModalProps';
import { cn } from '@/lib/utils/cn';
import styles from './ModalOpcoesBase.module.scss';

/**
 * Definição de uma ação exibida no modal de opções.
 * Use em listagens (articles/cards) para abrir um menu de ações em vez de navegar direto.
 */
export interface ModalOpcaoGroup {
    key: string;
    title?: string;
    actions: ModalOpcaoAction[];
}

export interface ModalOpcaoAction {
    key: string;
    label: string;
    icon?: ReactNode;
    onClick: () => void;
    /** Navegação SPA via Next.js Link (ex.: “Ver detalhes” com URL copiável / novo separador). */
    href?: string;
    /** Estilo danger (ex: Excluir) */
    danger?: boolean;
    /** Estilo primário (destaque) */
    primary?: boolean;
    disabled?: boolean;
    /** Texto do tooltip quando `disabled` (ex.: funcionalidade ainda não disponível). */
    disabledReason?: string;
    /** Spinner no botão (mutação em andamento) — alinhado à sidebar de movimentos. */
    loading?: boolean;
    /** Atributo para testes E2E no botão da ação. */
    testId?: string;
}

export interface ModalOpcoesBaseProps {
    /** Controla visibilidade do modal */
    open: boolean;
    /** Callback ao fechar (clique fora, ESC ou botão) */
    onClose: () => void;
    /** Título do modal (ex: "Opções do movimento") */
    title: string;
    /** Texto secundário (ex: "#123 - Descrição do item") */
    subtitle?: string;
    /** Lista de ações exibidas como botões em coluna (ignorada se `groups` estiver definido) */
    actions?: ModalOpcaoAction[];
    /** Ações agrupadas por seção (ex.: Status, Navegação, Perigo) */
    groups?: ModalOpcaoGroup[];
    /** Conteúdo customizado antes dos botões */
    children?: ReactNode;
    /** Largura em desktop (px). Em viewports estreitas usa-se largura total + corpo rolável (rollout listagens). Default: 400 */
    width?: number;
    /** Atributo para testes E2E no `Modal` raiz. */
    'data-testid'?: string;
    /** Acessibilidade: rótulo do diálogo. */
    'aria-label'?: string;
    /** Repor foco no elemento que abriu o modal (padrão Ant). `false` listagens abertas por clique na linha. */
    focusTriggerAfterClose?: boolean;
    /** Correr após animação de fecho (ex.: devolver foco à listagem sem competir com o `Modal`). */
    afterClose?: () => void;
    /** Shell visual premium (`waygestFormModal`) — alinhado ao modal de endereço PF. */
    premiumModalShell?: boolean;
    /**
     * Mutação em andamento: desativa todas as ações, impede fecho por máscara/X
     * e mostra spinner (padrão sidebar de movimentos).
     */
    loading?: boolean;
}

/**
 * Lista de ações (com ou sem grupos) — reutilizável em Modal ou painéis locais.
 */
export function ModalOpcoesActionsList({
    groups,
    actions = [],
    firstActionRef,
    loading = false,
}: {
    groups?: ModalOpcaoGroup[];
    actions?: ModalOpcaoAction[];
    firstActionRef?: React.RefObject<HTMLElement | null>;
    /** Desativa todas as ações (mutação global no modal). */
    loading?: boolean;
}) {
    const flatActions = groups?.length ? groups.flatMap((group) => group.actions) : actions;

    const renderActionButton = (action: ModalOpcaoAction, isFirst: boolean) => {
        const setFirstRef = (el: HTMLElement | null) => {
            if (isFirst && firstActionRef) {
                (firstActionRef as React.MutableRefObject<HTMLElement | null>).current = el;
            }
        };
        // Links de navegação (`href`) não herdam o `loading` global (ex.: Hub durante refresh).
        const actionDisabled = Boolean(action.disabled || (loading && !action.href));
        const actionLoading = Boolean(action.loading);
        const control =
            action.href && !actionDisabled ? (
                <Link
                    href={action.href}
                    prefetch={false}
                    onClick={() => action.onClick()}
                    data-testid={action.testId}
                    className={cn(
                        'ant-btn',
                        'ant-btn-lg',
                        'ant-btn-block',
                        action.primary ? 'ant-btn-primary' : 'ant-btn-default',
                        action.danger && 'ant-btn-dangerous',
                        styles.actionButton,
                        styles.actionLink,
                    )}
                    ref={setFirstRef}
                >
                    {action.icon ? (
                        <span className="ant-btn-icon" aria-hidden>
                            {action.icon}
                        </span>
                    ) : null}
                    <span>{action.label}</span>
                </Link>
            ) : (
                <Button
                    ref={setFirstRef as React.Ref<HTMLButtonElement>}
                    type={action.primary ? 'primary' : 'default'}
                    danger={action.danger}
                    icon={action.icon}
                    onClick={() => action.onClick()}
                    disabled={actionDisabled}
                    loading={actionLoading}
                    data-testid={action.testId}
                    block
                    size="large"
                    className={styles.actionButton}
                >
                    {action.label}
                </Button>
            );
        if (actionDisabled && action.disabledReason) {
            return (
                <Tooltip key={action.key} title={action.disabledReason}>
                    <span className={styles.disabledWrap}>{control}</span>
                </Tooltip>
            );
        }
        return <React.Fragment key={action.key}>{control}</React.Fragment>;
    };

    return (
        <div className={cn(styles.actionsList, groups?.length && styles.actionsListGrouped)}>
            {groups?.length
                ? groups.map((group) => (
                      <div key={group.key} className={styles.group}>
                          {group.title ? (
                              <Typography.Text type="secondary" className={styles.groupTitle}>
                                  {group.title}
                              </Typography.Text>
                          ) : null}
                          <div className={styles.groupActions}>
                              {group.actions.map((action) =>
                                  renderActionButton(action, action.key === flatActions[0]?.key),
                              )}
                          </div>
                      </div>
                  ))
                : flatActions.map((action) =>
                      renderActionButton(action, action.key === flatActions[0]?.key),
                  )}
        </div>
    );
}

/**
 * Modal base reutilizável para exibir opções de ação em listagens.
 * Cada módulo (ex: movimentos, clientes) pode criar um ModalOpcoes que usa este componente
 * e define as ações específicas (Detalhes, Editar, Excluir, etc.).
 */
export const ModalOpcoesBase: React.FC<ModalOpcoesBaseProps> = ({
    open,
    onClose,
    title,
    subtitle,
    actions = [],
    groups,
    children,
    width = 400,
    'data-testid': dataTestId,
    'aria-label': ariaLabel,
    focusTriggerAfterClose,
    afterClose,
    premiumModalShell = false,
    loading = false,
}) => {
    const firstActionRef = useRef<HTMLElement>(null);

    const responsiveModalLayout = useResponsiveModalProps();
    const premiumModalLayout = useWaygestFormModalProps();
    const modalLayout = premiumModalShell ? premiumModalLayout : responsiveModalLayout;
    const modalWidth = modalLayout.width ?? width;
    const modalCentered = modalLayout.centered ?? true;
    const modalStyles = premiumModalShell
        ? mergeWaygestFormModalBodyStyles(modalLayout)
        : modalLayout.styles;

    return (
        <Modal
            title={title}
            open={open}
            onCancel={() => {
                if (!loading) onClose();
            }}
            footer={null}
            width={modalWidth}
            destroyOnHidden
            keyboard={!loading}
            centered={modalCentered}
            styles={modalStyles}
            className={premiumModalShell ? premiumModalLayout.className : 'modal-opcoes-base'}
            zIndex={premiumModalShell ? premiumModalLayout.zIndex : undefined}
            maskClosable={loading ? false : premiumModalShell ? true : undefined}
            closable={!loading}
            closeIcon={<X aria-hidden />}
            data-testid={dataTestId}
            aria-label={ariaLabel}
            focusTriggerAfterClose={focusTriggerAfterClose ?? true}
            afterClose={afterClose}
            afterOpenChange={(isOpen) => {
                if (isOpen && !loading) {
                    firstActionRef.current?.focus();
                }
            }}
        >
            <Spin spinning={loading} className={styles.loadingSpin}>
                {subtitle ? <p className={styles.subtitle}>{subtitle}</p> : null}
                {children}
                <div className={cn(styles.actionsWrap, children && styles.actionsWrapWithChildren)}>
                    <ModalOpcoesActionsList
                        groups={groups}
                        actions={actions}
                        firstActionRef={firstActionRef}
                        loading={loading}
                    />
                </div>
            </Spin>
        </Modal>
    );
};
