'use client';

/**
 * Admin do token de ingest de logs (TASK-PPS-046).
 * Status sem plaintext; rotate mostra o valor uma vez; revoke com confirmação.
 * Nunca grava o token em localStorage/sessionStorage.
 */

import React, { useCallback, useState } from 'react';
import {
    Alert,
    Button,
    Card,
    Descriptions,
    Input,
    Modal,
    Popconfirm,
    Space,
    Spin,
    Tag,
    Tooltip,
    Typography,
} from 'antd';
import { useQueryClient } from '@tanstack/react-query';
import { message } from '@/lib/feedback/message';
import apiClient from '@/lib/api/client';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { getLaravelApiErrorMessage } from '@/lib/api/laravelApiErrorMessage';
import { queryKeys } from '@/lib/cache/queryKeys';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useProjetoWriteGates } from '@/features/projetos/hooks/useProjetoWriteGates';
import {
    extractIngestTokenPlainFromRotateBody,
    formatIngestTokenRotatedAt,
    ingestTokenStatusLabel,
    type ProjetoIngestTokenRotateEnvelope,
    type ProjetoIngestTokenStatus,
} from './projetoIngestToken';

export type ProjetoIngestTokenSectionProps = {
    projetoId: string;
};

export function ProjetoIngestTokenSection({ projetoId }: ProjetoIngestTokenSectionProps) {
    const queryClient = useQueryClient();
    const { canEditar, permsLoading, tooltipSemPermissao } = useProjetoWriteGates();

    const [rotateConfirmOpen, setRotateConfirmOpen] = useState(false);
    const [rotating, setRotating] = useState(false);
    const [revoking, setRevoking] = useState(false);
    const [tokenModalOpen, setTokenModalOpen] = useState(false);
    const [plainToken, setPlainToken] = useState<string | null>(null);

    const {
        data: envelope,
        isLoading,
        error,
        refetch,
    } = useQueryCache<{ data: ProjetoIngestTokenStatus }>({
        queryKey: queryKeys.projetos.ingestToken(projetoId),
        endpoint: API_ENDPOINTS.projetos.logs.token.show(projetoId),
        enabled: Boolean(projetoId) && canEditar && !permsLoading,
    });

    const status = envelope?.data;
    const statusError = error
        ? getLaravelApiErrorMessage(error, 'Não foi possível carregar o estado do token de ingest.')
        : null;

    const invalidate = useCallback(async () => {
        await queryClient.invalidateQueries({
            queryKey: queryKeys.projetos.ingestToken(projetoId),
        });
    }, [queryClient, projetoId]);

    const closeTokenModal = useCallback(() => {
        setTokenModalOpen(false);
        setPlainToken(null);
    }, []);

    const handleRotate = useCallback(async () => {
        setRotating(true);
        try {
            const res = await apiClient.post<ProjetoIngestTokenRotateEnvelope>(
                API_ENDPOINTS.projetos.logs.token.rotate(projetoId),
            );
            const plain = extractIngestTokenPlainFromRotateBody(res.data);
            if (!plain) {
                message.error(
                    'A rotação concluiu, mas o token não veio na resposta. Contate o suporte — não feche sem confirmar com a operação.',
                );
                await invalidate();
                setRotateConfirmOpen(false);
                return;
            }
            setPlainToken(plain);
            setRotateConfirmOpen(false);
            setTokenModalOpen(true);
            message.success('Token rotacionado. Copie agora — não será mostrado de novo.');
            await invalidate();
        } catch (e: unknown) {
            message.error(
                getLaravelApiErrorMessage(
                    e,
                    'Não foi possível rotacionar o token. Verifique permissão e addon de logs.',
                ),
            );
        } finally {
            setRotating(false);
        }
    }, [projetoId, invalidate]);

    const copyToken = useCallback(async () => {
        if (!plainToken) return;
        try {
            await navigator.clipboard.writeText(plainToken);
            message.success('Token copiado. Configure X-Project-Token nos clientes de ingest.');
        } catch {
            message.error('Não foi possível copiar. Selecione o texto e copie manualmente.');
        }
    }, [plainToken]);

    const handleRevoke = useCallback(async () => {
        setRevoking(true);
        try {
            await apiClient.post(API_ENDPOINTS.projetos.logs.token.revoke(projetoId));
            message.success('Token de ingest revogado. Clientes deixam de autenticar até nova rotação.');
            await invalidate();
        } catch (e: unknown) {
            message.error(
                getLaravelApiErrorMessage(e, 'Não foi possível revogar o token de ingest.'),
            );
        } finally {
            setRevoking(false);
        }
    }, [projetoId, invalidate]);

    if (permsLoading) {
        return (
            <Card title="Token de ingest de logs" size="small" style={{ marginBottom: 16 }}>
                <div style={{ textAlign: 'center', padding: 24 }}>
                    <Spin />
                </div>
            </Card>
        );
    }

    if (!canEditar) {
        return (
            <Card title="Token de ingest de logs" size="small" style={{ marginBottom: 16 }}>
                <Alert
                    type="info"
                    showIcon
                    message="Sem permissão para gerir o token de ingest"
                    description={tooltipSemPermissao('editar o projeto e gerir o token de ingest')}
                />
            </Card>
        );
    }

    const configurado = Boolean(status?.token_configurado);

    return (
        <>
            <Card
                title="Token de ingest de logs"
                size="small"
                style={{ marginBottom: 16 }}
                extra={
                    <Space wrap size="small">
                        <Tooltip title="Gera um novo token e invalida o anterior">
                            <Button
                                type="primary"
                                loading={rotating}
                                onClick={() => setRotateConfirmOpen(true)}
                                data-testid="ingest-token-rotate"
                            >
                                Rotacionar
                            </Button>
                        </Tooltip>
                        <Popconfirm
                            title="Revogar token de ingest?"
                            description="Os clientes deixam de autenticar até rotacionar de novo. Esta ação não pode ser desfeita."
                            okText="Revogar"
                            cancelText="Cancelar"
                            okButtonProps={{ danger: true, loading: revoking }}
                            disabled={!configurado || revoking}
                            onConfirm={() => void handleRevoke()}
                        >
                            <Button
                                danger
                                disabled={!configurado || revoking}
                                loading={revoking}
                                data-testid="ingest-token-revoke"
                            >
                                Revogar
                            </Button>
                        </Popconfirm>
                    </Space>
                }
            >
                <Alert
                    type="info"
                    showIcon
                    style={{ marginBottom: 16 }}
                    message="Header X-Project-Token"
                    description={
                        <>
                            Usado por clientes de ingest e extensão IDE. O valor em claro só aparece uma
                            vez após rotacionar — nunca é guardado nesta página.
                        </>
                    }
                />

                {statusError ? (
                    <Alert
                        type="error"
                        showIcon
                        style={{ marginBottom: 16 }}
                        message={statusError}
                        action={
                            <Button size="small" onClick={() => void refetch()}>
                                Tentar novamente
                            </Button>
                        }
                    />
                ) : null}

                {isLoading && !status ? (
                    <div style={{ textAlign: 'center', padding: 16 }}>
                        <Spin size="small" />
                    </div>
                ) : (
                    <Descriptions size="small" column={{ xs: 1, sm: 1, md: 3 }}>
                        <Descriptions.Item label="Estado">
                            <Tag color={configurado ? 'success' : 'default'}>
                                {status ? ingestTokenStatusLabel(status) : '—'}
                            </Tag>
                        </Descriptions.Item>
                        <Descriptions.Item label="Prefixo">
                            <Typography.Text code>
                                {status?.token_prefix?.trim() || '—'}
                            </Typography.Text>
                        </Descriptions.Item>
                        <Descriptions.Item label="Última rotação">
                            {formatIngestTokenRotatedAt(status?.token_rotated_at)}
                        </Descriptions.Item>
                    </Descriptions>
                )}
            </Card>

            <Modal
                title="Confirmar rotação do token"
                open={rotateConfirmOpen}
                onCancel={() => {
                    if (!rotating) setRotateConfirmOpen(false);
                }}
                onOk={() => void handleRotate()}
                okText="Rotacionar agora"
                cancelText="Cancelar"
                confirmLoading={rotating}
                destroyOnHidden
                width={480}
            >
                <Alert
                    type="warning"
                    showIcon
                    message="O token actual deixa de autenticar"
                    description="Clientes e extensões com o token antigo passam a receber 403. Salve o novo valor imediatamente após confirmar."
                />
            </Modal>

            <Modal
                title="Token rotacionado — copie agora"
                open={tokenModalOpen}
                onCancel={closeTokenModal}
                footer={
                    <Space wrap>
                        <Button type="primary" onClick={() => void copyToken()} data-testid="ingest-token-copy">
                            Copiar token
                        </Button>
                        <Button onClick={closeTokenModal}>Fechar</Button>
                    </Space>
                }
                destroyOnHidden
                width={520}
            >
                <Alert
                    type="warning"
                    showIcon
                    style={{ marginBottom: 12 }}
                    message="Só é mostrado uma vez"
                    description="Salve o token nos clientes de ingest (header X-Project-Token). Depois de fechar este diálogo, não será possível voltar a vê-lo."
                />
                <Typography.Paragraph type="secondary" style={{ marginBottom: 8 }}>
                    Header:{' '}
                    <Typography.Text code>X-Project-Token</Typography.Text>
                </Typography.Paragraph>
                <Input.TextArea
                    value={plainToken ?? ''}
                    readOnly
                    autoSize={{ minRows: 3, maxRows: 6 }}
                    style={{ fontFamily: 'monospace', fontSize: 12 }}
                    data-testid="ingest-token-plaintext"
                />
            </Modal>
        </>
    );
}
