'use client';

import React, { useMemo, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
import { Button, Space, Card, Upload, Typography, Select } from 'antd';
import { message } from '@/lib/feedback/message';
import { Paperclip, Send } from 'lucide-react';
import { ICON_SIZE_MD } from '@/components/icons';
import type { UploadFile } from 'antd/es/upload';
import apiClient from '@/lib/api/client';
import { createIdempotencyKey, idempotencyKeyHeaders } from '@/lib/api/idempotencyKey';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { extractApiErrorMessage } from '@/lib/api/extractApiErrorMessage';
import { confirmDialog } from '@/lib/feedback/confirmDialog';
import { useQueryCache } from '@/hooks/useQueryCache';
import { queryKeys } from '@/lib/cache/queryKeys';
import 'react-quill/dist/quill.snow.css';
import type { ChamadoCommentMacroContext } from './ChamadoCommentMacroPicker';
import { ChamadoCommentMacroPicker } from './ChamadoCommentMacroPicker';
import { mergeMacroHtmlIntoEditor } from '@/features/suporte/chamados/respostas-rapidas/chamadosTemplateService';
import styles from './ChamadoCommentForm.module.scss';

const ReactQuill = dynamic(() => import('react-quill'), { ssr: false });

/** Alinhado a `StoreChamadoComentarioRequest` na API (HTML sanitizado no servidor). */
const COMENTARIO_MAX_LENGTH = 50000;

type QuillModules = Record<string, unknown>;

type KbArtigoListItem = {
    id: number;
    titulo: string;
    slug?: string | null;
};

type KbArtigosPaginated = {
    data: KbArtigoListItem[];
};

interface ChamadoCommentFormProps {
    chamadoId: number | string;
    endpoint: string;
    onSuccess?: () => void;
    placeholder?: string;
    /** GET lista de artigos KB (`/v1/suporte/kb/artigos`) — mostra select para referência no comentário. */
    kbArtigosListEndpoint?: string;
    /** Ativa picker de macros (`canned_response`) com substituição de variáveis do chamado. */
    macroContext?: ChamadoCommentMacroContext;
    /** Oculta tipo interno para solicitantes (alinhado a `viewComentariosInternos` na API). */
    isAgenteSuporte?: boolean;
}

export function ChamadoCommentForm({
    chamadoId,
    endpoint,
    onSuccess,
    placeholder = 'Resposta ao cliente ou nota interna…',
    kbArtigosListEndpoint,
    macroContext,
    isAgenteSuporte = true,
}: ChamadoCommentFormProps) {
    const [loading, setLoading] = useState(false);
    const idempotencyKeyRef = useRef(createIdempotencyKey());
    const [tipo, setTipo] = useState<'publico' | 'interno'>(isAgenteSuporte ? 'interno' : 'publico');
    const [fileList, setFileList] = useState<UploadFile[]>([]);
    const [editorHtml, setEditorHtml] = useState('');
    const [kbArtigoId, setKbArtigoId] = useState<number | null>(null);

    const { data: kbPaginated, isLoading: kbArtigosLoading } = useQueryCache<KbArtigosPaginated>({
        queryKey: queryKeys.suporte.kb.artigos.chamadoComentario(),
        endpoint: kbArtigosListEndpoint ?? API_ENDPOINTS.suporte.kb.artigos.index,
        params: { per_page: 200, page: 1 },
        enabled: Boolean(kbArtigosListEndpoint),
        staleTime: 2 * 60 * 1000,
    });

    const kbOptions = useMemo(() => {
        const rows = kbPaginated?.data ?? [];
        return rows.map((a) => ({
            value: a.id,
            label: a.slug ? `${a.titulo} (${a.slug})` : a.titulo,
        }));
    }, [kbPaginated]);

    const modules = useMemo<QuillModules>(
        () => ({
            toolbar: [
                [{ header: [1, 2, false] }],
                ['bold', 'italic', 'underline', 'strike'],
                [{ list: 'ordered' }, { list: 'bullet' }],
                ['link', 'image'],
                ['clean'],
            ],
        }),
        []
    );

    const handleSubmit = async () => {
        try {
            const comentario = editorHtml.replace(/<p><br><\/p>/g, '').trim();
            const vazio = !comentario || comentario === '<p><br></p>';
            if (vazio && kbArtigoId == null) {
                message.warning('Escreva o comentário ou selecione um artigo da base de conhecimento.');
                return;
            }
            if (comentario.length > COMENTARIO_MAX_LENGTH) {
                message.warning(`O conteúdo excede ${COMENTARIO_MAX_LENGTH} caracteres.`);
                return;
            }

            setLoading(true);
            const body: Record<string, unknown> = {
                comentario: vazio ? '' : comentario,
                tipo,
                enviar_email: tipo === 'publico',
            };
            if (kbArtigoId != null) {
                body.kb_artigo_id = kbArtigoId;
            }
            const res = await apiClient.post<{ id: number }>(endpoint, body, {
                headers: idempotencyKeyHeaders(idempotencyKeyRef.current),
            });
            const comentarioId = res.data?.id;

            const files = fileList
                .map((f) => f.originFileObj)
                .filter((f): f is NonNullable<UploadFile['originFileObj']> => f != null);

            if (files.length > 0 && comentarioId) {
                const anexoBase = API_ENDPOINTS.suporte.chamados.anexos.store(chamadoId);
                for (const arquivo of files) {
                    const fd = new FormData();
                    fd.append('arquivo', arquivo);
                    fd.append('comentario_id', String(comentarioId));
                    await apiClient.post(anexoBase, fd);
                }
            }

            message.success('Comentário adicionado com sucesso!');
            setEditorHtml('');
            setFileList([]);
            setKbArtigoId(null);
            setTipo(isAgenteSuporte ? 'interno' : 'publico');
            idempotencyKeyRef.current = createIdempotencyKey();
            onSuccess?.();
        } catch (error: unknown) {
            const err = error as { response?: { status?: number; data?: { message?: string } } };
            if (err.response?.status === 429) {
                message.warning(
                    'Muitos comentários em pouco tempo. Asalve um minuto e tente novamente.'
                );
                return;
            }
            message.error(extractApiErrorMessage(error, 'Erro ao adicionar comentário'));
        } finally {
            setLoading(false);
        }
    };

    const handleSelectTipo = (next: 'publico' | 'interno') => {
        if (next === 'publico' && tipo !== 'publico') {
            confirmDialog({
                title: 'Tornar comentário público?',
                content:
                    'Comentários públicos são visíveis ao cliente e podem enviar e-mail automaticamente. Confirma que deseja continuar?',
                okText: 'Sim, tornar público',
                cancelText: 'Cancelar',
                onOk: () => setTipo('publico'),
            });
            return;
        }
        setTipo(next);
    };

    return (
        <Card size="small" style={{ marginBottom: 16 }} className={styles.root}>
            {macroContext ? (
                <ChamadoCommentMacroPicker
                    macroContext={macroContext}
                    onInsertHtml={(html) => setEditorHtml((prev) => mergeMacroHtmlIntoEditor(prev, html))}
                />
            ) : null}
            <div className="chamado-comentario-form" style={{ marginBottom: 12 }}>
                <ReactQuill
                    theme="snow"
                    value={editorHtml}
                    onChange={setEditorHtml}
                    placeholder={placeholder}
                    modules={modules as import('quill').StringMap}
                />
            </div>

            {kbArtigosListEndpoint ? (
                <div style={{ marginBottom: 12 }}>
                    <Typography.Text type="secondary" style={{ display: 'block', marginBottom: 6 }}>
                        Artigo da base de conhecimento
                    </Typography.Text>
                    <Select
                        allowClear
                        showSearch
                        placeholder="Selecionar artigo publicado…"
                        style={{ width: '100%' }}
                        options={kbOptions}
                        value={kbArtigoId ?? undefined}
                        onChange={(v) => setKbArtigoId(typeof v === 'number' ? v : null)}
                        loading={kbArtigosLoading}
                        optionFilterProp="label"
                    />
                </div>
            ) : null}

            <Space wrap style={{ marginBottom: 12 }}>
                <span style={{ color: '#595959' }}>Tipo:</span>
                <Button.Group>
                    <Button type={tipo === 'publico' ? 'primary' : 'default'} onClick={() => handleSelectTipo('publico')}>
                        Público
                    </Button>
                    {isAgenteSuporte ? (
                        <Button type={tipo === 'interno' ? 'primary' : 'default'} onClick={() => handleSelectTipo('interno')}>
                            Interno
                        </Button>
                    ) : null}
                </Button.Group>
            </Space>

            {tipo === 'publico' && (
                <Typography.Paragraph type="secondary" style={{ marginBottom: 12, fontSize: 13 }}>
                    Comentários públicos enviam automaticamente e-mail ao cliente (resposta na mesma conversa,
                    quando o chamado tiver origem por e-mail).
                </Typography.Paragraph>
            )}

            <div className={styles.actionsRow}>
                <Upload
                    fileList={fileList}
                    onChange={({ fileList: fl }) => setFileList(fl)}
                    beforeUpload={() => false}
                    multiple
                    maxCount={8}
                >
                    <Button icon={<Paperclip size={ICON_SIZE_MD} aria-hidden />}>Anexos</Button>
                </Upload>
                <div className={styles.submitSticky}>
                    <Button
                        type="primary"
                        icon={<Send size={ICON_SIZE_MD} aria-hidden />}
                        loading={loading}
                        disabled={loading}
                        onClick={() => void handleSubmit()}
                        data-testid="chamado-comentario-enviar"
                    >
                        Enviar comentário
                    </Button>
                </div>
            </div>
        </Card>
    );
}
