'use client';

import React, { useEffect, useMemo, useRef, useState } from 'react';
import { Alert, Button, Modal, Progress, Space, Table, Tag, Typography, Upload } from 'antd';
import type { UploadFile } from 'antd/es/upload';
import { Download, Upload as UploadIcon } from 'lucide-react';

import { ICON_SIZE_MD } from '@/components/icons';
import {
    mergeWaygestFormModalBodyStyles,
    useWaygestFormModalProps,
    waygestFormModalFooterClassName,
} from '@/hooks/useWaygestFormModalProps';
import { message } from '@/lib/feedback/message';
import { getLaravelApiErrorMessage } from '@/lib/api/laravelApiErrorMessage';
import { recordProdutoImportCompleted } from '@/lib/telemetry/produtoSoftwareTelemetry';
import {
    downloadProdutoImportCsvErros,
    downloadProdutoImportCsvFalhasCommit,
} from './produtoImportCsvErrosDownload';
import {
    importarProdutoCsvCommit,
    importarProdutoCsvDryRun,
} from './produtoImportCsvService';
import { downloadProdutoImportCsvTemplate } from './produtoImportCsvTemplate';
import {
    PRODUTO_IMPORT_CSV_MAX_LINHAS_DRY_RUN,
    type ProdutoImportCsvBatch,
    type ProdutoImportCsvLinhaDetalhe,
    type ProdutoImportCsvLinhaStatus,
} from './types';
import { useProdutoImportCsvPolling } from './useProdutoImportCsvPolling';

const { Paragraph, Text } = Typography;

export type ProdutoImportCsvModalProps = {
    open: boolean;
    onClose: () => void;
    /** Refetch após commit concluído com importações. */
    onSuccess?: () => void | Promise<void>;
};

type Step = 'upload' | 'preview' | 'progress' | 'done';

const STATUS_TAG_COLOR: Record<ProdutoImportCsvLinhaStatus, string> = {
    ok: 'success',
    aviso: 'warning',
    erro: 'error',
};

const STATUS_LABEL: Record<ProdutoImportCsvLinhaStatus, string> = {
    ok: 'OK',
    aviso: 'Aviso',
    erro: 'Erro',
};

const TEST_ID = 'produto-import-csv-modal';

function importProgressPercent(batch: ProdutoImportCsvBatch | null): number {
    if (!batch) return 0;
    if (batch.status === 'done' || batch.status === 'failed' || batch.status === 'cancelled') {
        return 100;
    }
    if (batch.status === 'processing') return 55;
    if (batch.status === 'queued') return 15;
    return 0;
}

function isCsvFile(file: File): boolean {
    return /\.csv$/i.test(file.name) || file.type === 'text/csv';
}

/**
 * Modal import CSV tipológico: upload → dry-run → relatório por linha → commit + poll.
 * Reutiliza UX de `ProjetoEntidadeImportCsvModal` (requisitos/módulos SC).
 */
export function ProdutoImportCsvModal({ open, onClose, onSuccess }: ProdutoImportCsvModalProps) {
    const modalLayout = useWaygestFormModalProps();
    const importPoll = useProdutoImportCsvPolling();

    const [fileList, setFileList] = useState<UploadFile[]>([]);
    const [busy, setBusy] = useState(false);
    const [step, setStep] = useState<Step>('upload');
    const [preview, setPreview] = useState<ProdutoImportCsvBatch | null>(null);
    const processedTerminalRef = useRef<string | null>(null);

    const resetState = () => {
        setFileList([]);
        setStep('upload');
        setPreview(null);
        setBusy(false);
        processedTerminalRef.current = null;
        importPoll.reset();
    };

    useEffect(() => {
        if (!importPoll.isTerminal || !importPoll.batch) {
            return;
        }

        const terminalKey = `${importPoll.batch.import_id}:${importPoll.batch.status}`;
        if (processedTerminalRef.current === terminalKey) {
            return;
        }
        processedTerminalRef.current = terminalKey;

        const batch = importPoll.batch;
        setStep('done');

        if (batch.status === 'cancelled') {
            message.info('Importação cancelada.');
            return;
        }

        if (batch.status === 'failed') {
            message.error(
                batch.error_message ||
                    'A importação falhou. Verifique o arquivo e tente novamente.',
            );
            recordProdutoImportCompleted({
                rows_ok: 0,
                rows_err: batch.linhas_erro ?? 0,
                result: 'failed',
            });
            return;
        }

        const importadas = batch.linhas_importadas ?? 0;
        const falhasCommit = batch.relatorio?.falhas_commit?.length ?? 0;

        recordProdutoImportCompleted({
            rows_ok: importadas,
            rows_err: falhasCommit + (batch.linhas_erro ?? 0),
            result: importadas > 0 ? (falhasCommit > 0 ? 'partial' : 'ok') : 'failed',
        });

        if (importadas > 0 && falhasCommit === 0) {
            message.success(
                importadas === 1
                    ? '1 linha importada com sucesso.'
                    : `${importadas} linhas importadas com sucesso.`,
            );
            void onSuccess?.();
            return;
        }

        if (importadas > 0 && falhasCommit > 0) {
            message.warning(
                `Importação parcial: ${importadas} importada(s), ${falhasCommit} falha(s) no commit.`,
            );
            void onSuccess?.();
            return;
        }

        message.error('Nenhum registro foi importado. Corrija o arquivo ou tente novamente.');
    }, [importPoll.batch, importPoll.isTerminal, onSuccess]);

    const handleClose = () => {
        if (busy || importPoll.polling) return;
        resetState();
        onClose();
    };

    const handlePreview = async () => {
        const file = fileList[0]?.originFileObj;
        if (!file) {
            message.warning('Selecione um arquivo CSV.');
            return;
        }

        setBusy(true);
        try {
            const data = await importarProdutoCsvDryRun(file);
            setPreview(data);
            setStep('preview');
        } catch (error: unknown) {
            message.error(
                getLaravelApiErrorMessage(
                    error,
                    'Não foi possível pré-visualizar o CSV. Verifique o arquivo e tente novamente.',
                ),
            );
        } finally {
            setBusy(false);
        }
    };

    const handleCommit = async () => {
        const importId = preview?.import_id || preview?.batch_id || preview?.id;
        if (!importId) {
            message.warning('Selecione um arquivo CSV.');
            return;
        }

        const importaveis = (preview?.linhas_ok ?? 0) + (preview?.linhas_aviso ?? 0);
        if (importaveis === 0) {
            message.warning('Não há linhas válidas para importar. Corrija o CSV.');
            return;
        }

        setBusy(true);
        try {
            const data = await importarProdutoCsvCommit(importId);
            setStep('progress');
            importPoll.start(data.import_id || importId, data);
        } catch (error: unknown) {
            message.error(
                getLaravelApiErrorMessage(
                    error,
                    'Não foi possível confirmar a importação. Tente novamente.',
                ),
            );
        } finally {
            setBusy(false);
        }
    };

    const previewLinhas = useMemo((): ProdutoImportCsvLinhaDetalhe[] => {
        return preview?.relatorio?.linhas ?? [];
    }, [preview]);

    const errosDryRun = useMemo(
        () => previewLinhas.filter((l) => l.status === 'erro' || l.status === 'aviso'),
        [previewLinhas],
    );
    const falhasCommit = importPoll.batch?.relatorio?.falhas_commit ?? [];
    const canCommit =
        (preview?.linhas_ok ?? 0) + (preview?.linhas_aviso ?? 0) > 0 &&
        preview?.status === 'dry_run';

    const progressBatch = importPoll.batch ?? preview;
    const progressPercent = importProgressPercent(progressBatch);
    const progressException =
        progressBatch?.status === 'failed' || importPoll.pollError === 'timeout';

    const footer = (
        <div className={waygestFormModalFooterClassName}>
            {step === 'progress' ? (
                <Button onClick={handleClose} disabled={importPoll.polling}>
                    {importPoll.polling ? 'A processar…' : 'Fechar'}
                </Button>
            ) : step === 'done' ? (
                <>
                    {falhasCommit.length > 0 ? (
                        <Button
                            onClick={() => downloadProdutoImportCsvFalhasCommit(falhasCommit)}
                            data-testid={`${TEST_ID}-falhas-commit-download`}
                        >
                            Baixar falhas do commit
                        </Button>
                    ) : null}
                    <Button
                        type="primary"
                        onClick={() => {
                            resetState();
                            onClose();
                        }}
                        data-testid={`${TEST_ID}-fechar-done`}
                    >
                        Fechar
                    </Button>
                </>
            ) : step === 'upload' ? (
                <>
                    <Button
                        icon={<Download size={ICON_SIZE_MD} aria-hidden />}
                        onClick={() => downloadProdutoImportCsvTemplate()}
                        disabled={busy}
                        data-testid={`${TEST_ID}-download-template`}
                    >
                        Baixar template
                    </Button>
                    <Button onClick={handleClose} disabled={busy}>
                        Cancelar
                    </Button>
                    <Button
                        type="primary"
                        loading={busy}
                        disabled={fileList.length === 0}
                        onClick={() => void handlePreview()}
                        data-testid={`${TEST_ID}-preview`}
                    >
                        Pré-visualizar
                    </Button>
                </>
            ) : (
                <>
                    <Button onClick={() => setStep('upload')} disabled={busy}>
                        Voltar
                    </Button>
                    <Button
                        onClick={() => downloadProdutoImportCsvErros(errosDryRun)}
                        disabled={errosDryRun.length === 0}
                        data-testid={`${TEST_ID}-erros-download`}
                    >
                        Baixar erros
                    </Button>
                    <Button
                        type="primary"
                        loading={busy}
                        disabled={!canCommit}
                        onClick={() => void handleCommit()}
                        data-testid={`${TEST_ID}-commit`}
                    >
                        Confirmar importação
                    </Button>
                </>
            )}
        </div>
    );

    const modalWidth =
        step === 'preview' || step === 'done'
            ? Math.max(Number(modalLayout.width ?? 720), 920)
            : step === 'progress'
              ? 560
              : (modalLayout.width ?? 720);

    return (
        <Modal
            title="Importar programas e superfícies (CSV)"
            open={open}
            onCancel={handleClose}
            destroyOnHidden
            width={modalWidth}
            centered={modalLayout.centered ?? true}
            className={modalLayout.className}
            styles={mergeWaygestFormModalBodyStyles(modalLayout, {
                body: { maxHeight: 'min(75vh, calc(100vh - 180px))', overflowY: 'auto' },
            })}
            zIndex={modalLayout.zIndex}
            footer={footer}
            data-testid={TEST_ID}
        >
            {step === 'progress' || (step === 'done' && importPoll.batch) ? (
                <Space direction="vertical" size={12} style={{ width: '100%' }}>
                    <Paragraph style={{ marginBottom: 0 }}>
                        {step === 'progress'
                            ? 'A importação está em fila. Não feche esta janela até concluir.'
                            : 'Processamento concluído.'}
                    </Paragraph>
                    <Progress
                        percent={progressPercent}
                        status={
                            progressException
                                ? 'exception'
                                : step === 'done' && progressBatch?.status === 'done'
                                  ? 'success'
                                  : 'active'
                        }
                        aria-label="Progresso da importação CSV"
                    />
                    <Text type="secondary" style={{ fontSize: 12 }}>
                        {progressBatch?.status === 'queued'
                            ? 'Na fila…'
                            : progressBatch?.status === 'processing'
                              ? 'A processar linhas…'
                              : progressBatch?.status === 'done'
                                ? `Importados: ${progressBatch.linhas_importadas ?? 0}. Falhas no commit: ${falhasCommit.length}.`
                                : progressBatch?.status === 'failed'
                                  ? progressBatch.error_message || 'A importação falhou.'
                                  : importPoll.pollError === 'timeout'
                                    ? 'Tempo esgotado ao asalvar o processamento. Atualize a listagem ou tente novamente.'
                                    : null}
                    </Text>
                    {step === 'done' && falhasCommit.length > 0 ? (
                        <Alert
                            type="warning"
                            showIcon
                            message={`${falhasCommit.length} linha(s) falharam no commit. Baixe o relatório para corrigir.`}
                        />
                    ) : null}
                </Space>
            ) : step === 'upload' ? (
                <>
                    <Paragraph type="secondary" style={{ marginBottom: 8 }}>
                        Ficheiro CSV em <Text strong>UTF-8</Text> (máx.{' '}
                        {PRODUTO_IMPORT_CSV_MAX_LINHAS_DRY_RUN} linhas no dry-run). A pré-visualização{' '}
                        <Text strong>não grava</Text> registos — só após confirmar a importação.
                    </Paragraph>
                    <Paragraph style={{ marginBottom: 16, fontSize: 13 }}>
                        Obrigatório: <Text code>programa_nome</Text>, <Text code>programa_codigo</Text>,{' '}
                        <Text code>superficie_nome</Text>, <Text code>superficie_codigo</Text>,{' '}
                        <Text code>categoria_codigo</Text>. Opcionais: <Text code>ciclo_vida</Text>,{' '}
                        <Text code>visao_produto</Text>.
                    </Paragraph>

                    <Upload.Dragger
                        accept=".csv,text/csv"
                        maxCount={1}
                        fileList={fileList}
                        disabled={busy}
                        beforeUpload={(file) => {
                            if (!isCsvFile(file)) {
                                message.error('Use um arquivo .csv');
                                return Upload.LIST_IGNORE;
                            }
                            setPreview(null);
                            setStep('upload');
                            setFileList([
                                {
                                    uid: file.uid,
                                    name: file.name,
                                    status: 'done',
                                    originFileObj: file,
                                },
                            ]);
                            return false;
                        }}
                        onRemove={() => {
                            if (busy) return false;
                            setFileList([]);
                            setPreview(null);
                        }}
                        data-testid={`${TEST_ID}-upload`}
                    >
                        <p className="ant-upload-drag-icon">
                            <UploadIcon size={ICON_SIZE_MD} aria-hidden />
                        </p>
                        <p className="ant-upload-text">Arraste o CSV ou clique para selecionar</p>
                    </Upload.Dragger>
                </>
            ) : (
                <>
                    {preview ? (
                        <Paragraph style={{ marginBottom: 12 }}>
                            Pré-visualização: {preview.linhas_ok} OK, {preview.linhas_aviso} aviso(s),{' '}
                            {preview.linhas_erro} erro(s) — total {preview.total_linhas} linha(s).
                        </Paragraph>
                    ) : null}
                    {!canCommit ? (
                        <Alert
                            type="error"
                            showIcon
                            style={{ marginBottom: 12 }}
                            message="Não há linhas válidas para importar. Corrija o CSV e volte a pré-visualizar."
                        />
                    ) : null}
                    <Table
                        size="small"
                        rowKey={(row: any) => `${row.linha}-${row.status}`}
                        pagination={{ pageSize: 8, hideOnSinglePage: true }}
                        scroll={{ x: 640 }}
                        dataSource={previewLinhas}
                        locale={{ emptyText: 'Sem linhas no relatório.' }}
                        data-testid={`${TEST_ID}-preview-table`}
                        columns={[
                            {
                                title: 'Linha',
                                dataIndex: 'linha',
                                width: 72,
                            },
                            {
                                title: 'Estado',
                                dataIndex: 'status',
                                width: 100,
                                render: (status: ProdutoImportCsvLinhaStatus) => (
                                    <Tag color={STATUS_TAG_COLOR[status]}>
                                        {STATUS_LABEL[status] ?? status}
                                    </Tag>
                                ),
                            },
                            {
                                title: 'Detalhe',
                                key: 'motivo',
                                render: (_: unknown, row: ProdutoImportCsvLinhaDetalhe) =>
                                    row.motivo || '—',
                            },
                        ]}
                    />
                    {errosDryRun.length > 0 ? (
                        <Paragraph type="danger" style={{ marginTop: 12, marginBottom: 0 }}>
                            {errosDryRun.length} linha(s) com erro ou aviso — corrija antes de confirmar
                            ou importe só as válidas.
                        </Paragraph>
                    ) : null}
                </>
            )}
        </Modal>
    );
}
