'use client';

import { Download, Eye, File, FileText, Image as ImageIcon, Paperclip, Trash2, Upload as UploadIcon } from 'lucide-react';
import { Button, Image, List, Popconfirm, Space, Tag, Tooltip, Typography, Upload } from 'antd';
import { message } from '@/lib/feedback/message';
import { ICON_SIZE_MD, iconTokenSize } from '@/components/icons';
import { ListagemEmptyState } from '@/components/listings';
import React, { useState, useEffect, useCallback, useRef } from 'react';
import type { UploadProps } from 'antd';
import apiClient from '@/lib/api/client';
import { formatDate } from '@/lib/utils/export';
import styles from './TarefaAnexos.module.scss';
import { LoadingState } from '@/components/ui/LoadingState';

const { Text } = Typography;
const { Dragger } = Upload;

interface TarefaAnexo {
    id: number;
    nome_original: string;
    nome_arquivo: string;
    caminho?: string;
    url?: string;
    mime_type?: string;
    tamanho: number;
    tamanho_formatado?: string;
    descricao?: string;
    is_imagem?: boolean;
    is_pdf?: boolean;
    usuario?: {
        id: number;
        nome: string;
    };
    created_at: string;
}

interface TarefaAnexosProps {
    tarefaId: number | string;
    endpoint: string;
    initialAnexos?: TarefaAnexo[];
    canUpload?: boolean;
    uploadDisabledReason?: string;
    canDeleteAnexo?: (anexoUsuarioId?: number) => boolean;
    deleteDisabledReason?: string;
    onUploadSuccess?: () => void;
    onDeleteSuccess?: () => void;
}

function normalizeAnexosPayload(data: unknown): TarefaAnexo[] {
    if (!data || typeof data !== 'object') {
        return [];
    }

    const record = data as Record<string, unknown>;

    if (Array.isArray(record.anexos)) {
        return record.anexos as TarefaAnexo[];
    }

    if (Array.isArray(data)) {
        return data as TarefaAnexo[];
    }

    return [];
}

export function TarefaAnexos({
    tarefaId,
    endpoint,
    initialAnexos,
    canUpload = true,
    uploadDisabledReason,
    canDeleteAnexo,
    deleteDisabledReason,
    onUploadSuccess,
    onDeleteSuccess,
}: TarefaAnexosProps) {
    const [anexos, setAnexos] = useState<TarefaAnexo[]>(initialAnexos ?? []);
    const [loading, setLoading] = useState(false);
    const [uploading, setUploading] = useState(false);
    const [previewImage, setPreviewImage] = useState<string | null>(null);
    const uploadAreaRef = useRef<HTMLDivElement>(null);

    const openFilePicker = () => {
        uploadAreaRef.current?.querySelector<HTMLInputElement>('input[type="file"]')?.click();
    };

    const loadAnexos = useCallback(async () => {
        try {
            setLoading(true);
            const response = await apiClient.get(endpoint);
            const loaded = normalizeAnexosPayload(response.data);
            setAnexos(loaded);
        } catch (error) {
            console.error('Erro ao carregar anexos:', error);
        } finally {
            setLoading(false);
        }
    }, [endpoint]);

    useEffect(() => {
        if (initialAnexos?.length) {
            setAnexos(initialAnexos);
        }
    }, [initialAnexos]);

    useEffect(() => {
        loadAnexos();
    }, [tarefaId, endpoint, loadAnexos]);

    const handleUpload: UploadProps['customRequest'] = async ({
        file,
        onSuccess,
        onError,
        onProgress,
    }) => {
        const formData = new FormData();
        formData.append('arquivo', file as File);
        const fileWithDesc = file as File & { descricao?: string };
        if (fileWithDesc.descricao) {
            formData.append('descricao', fileWithDesc.descricao);
        }

        try {
            setUploading(true);
            const response = await apiClient.post(endpoint, formData, {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
                onUploadProgress: (progressEvent) => {
                    if (progressEvent.total) {
                        const percent = Math.round(
                            (progressEvent.loaded * 100) / progressEvent.total
                        );
                        onProgress?.({ percent });
                    }
                },
            });

            const uploaded = (response.data as { anexo?: TarefaAnexo })?.anexo;
            if (uploaded?.id) {
                setAnexos((prev) => {
                    const exists = prev.some((item) => item.id === uploaded.id);
                    return exists ? prev : [uploaded, ...prev];
                });
            }

            await loadAnexos();
            onUploadSuccess?.();

            const fileName = typeof file === 'string' ? file : (file as File).name || 'arquivo';
            message.success(`${fileName} enviado com sucesso!`);
            onSuccess?.(file);
        } catch (error: unknown) {
            const apiError = error as { response?: { data?: { message?: string } } };
            const fileName = typeof file === 'string' ? file : (file as File).name || 'arquivo';
            message.error(apiError?.response?.data?.message || `Erro ao enviar ${fileName}`);
            onError?.(error as Error);
        } finally {
            setUploading(false);
        }
    };

    const handleDelete = async (anexoId: number) => {
        try {
            await apiClient.delete(`${endpoint}/${anexoId}`);
            message.success('Anexo excluído com sucesso!');
            loadAnexos();
            onDeleteSuccess?.();
        } catch (error: unknown) {
            const apiError = error as { response?: { data?: { message?: string } } };
            message.error(apiError?.response?.data?.message || 'Erro ao excluir anexo');
        }
    };

    const handleDownload = async (anexo: TarefaAnexo) => {
        try {
            const response = await apiClient.get(`${endpoint}/${anexo.id}/download`, {
                responseType: 'blob',
            });

            const url = window.URL.createObjectURL(new Blob([response.data]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', anexo.nome_original);
            document.body.appendChild(link);
            link.click();
            link.remove();
            window.URL.revokeObjectURL(url);
        } catch (error: unknown) {
            const apiError = error as { response?: { data?: { message?: string } } };
            message.error(apiError?.response?.data?.message || 'Erro ao baixar arquivo');
        }
    };

    const fetchAnexoBlobUrl = async (anexo: TarefaAnexo): Promise<string> => {
        const response = await apiClient.get(`${endpoint}/${anexo.id}/download`, {
            responseType: 'blob',
        });
        return window.URL.createObjectURL(new Blob([response.data]));
    };

    const handlePreview = async (anexo: TarefaAnexo) => {
        try {
            const blobUrl = await fetchAnexoBlobUrl(anexo);
            if (anexo.is_imagem) {
                setPreviewImage(blobUrl);
                return;
            }
            window.open(blobUrl, '_blank');
        } catch (error: unknown) {
            const apiError = error as { response?: { data?: { message?: string } } };
            message.error(apiError?.response?.data?.message || 'Erro ao abrir arquivo');
        }
    };

    const formatarTamanho = (bytes: number) => {
        if (bytes === 0) return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
    };

    const getFileIcon = (anexo: TarefaAnexo) => {
        if (anexo.is_imagem) {
            return <ImageIcon size={24} style={{ color: 'var(--primary, #27132e)' }} aria-hidden />;
        }
        if (anexo.is_pdf) {
            return <FileText size={24} style={{ color: '#ff4d4f' }} aria-hidden />;
        }
        return <File size={24} aria-hidden />;
    };

    const uploadProps: UploadProps = {
        accept: '*',
        multiple: true,
        customRequest: handleUpload,
        showUploadList: false,
        disabled: uploading || !canUpload,
    };

    return (
        <div className={styles.root}>
            {canUpload ? (
                <div ref={uploadAreaRef}>
                    <Dragger {...uploadProps} className={styles.uploadDragger}>
                        <div className={styles.uploadInner}>
                            <span className={styles.uploadIconWrap} aria-hidden>
                                <UploadIcon size={ICON_SIZE_MD} />
                            </span>
                            <div className={styles.uploadCopy}>
                                <p className={styles.uploadTitle}>Adicionar arquivos</p>
                                <p className={styles.uploadHint}>
                                    Toque para selecionar ou arraste aqui · múltiplos arquivos · máx. 10MB
                                </p>
                            </div>
                        </div>
                    </Dragger>
                </div>
            ) : uploadDisabledReason ? (
                <Typography.Text type="secondary" className={styles.uploadDisabledReason}>
                    {uploadDisabledReason}
                </Typography.Text>
            ) : null}

            {uploading && (
                <div className={styles.uploadingBar} role="status" aria-live="polite">
                    <UploadIcon className="animate-spin" size={ICON_SIZE_MD} aria-hidden />
                    Enviando arquivo…
                </div>
            )}

            {loading && anexos.length === 0 ? (
                <div className={styles.loadingState} aria-live="polite">
                    <LoadingState label="Carregando anexos…" />
                </div>
            ) : anexos.length === 0 ? (
                <ListagemEmptyState
                    type="info"
                    icon={<Paperclip size={iconTokenSize.xl} aria-hidden />}
                    message="Nenhum anexo ainda"
                    description={
                        canUpload
                            ? 'Envie documentos, imagens ou PDFs para centralizar os arquivos desta tarefa.'
                            : uploadDisabledReason ??
                              'Esta tarefa ainda não tem arquivos anexados.'
                    }
                    ctaLabel={canUpload ? 'Adicionar arquivos' : undefined}
                    onCta={canUpload ? openFilePicker : undefined}
                    className={styles.emptyState}
                    data-testid="tarefa-anexos-empty"
                />
            ) : (
                <List
                    className={styles.anexoList}
                    loading={loading}
                    dataSource={anexos}
                    renderItem={(anexo) => {
                        const podeExcluir =
                            canDeleteAnexo?.(anexo.usuario?.id) ??
                            (canDeleteAnexo == null);

                        return (
                        <List.Item
                            actions={[
                                ...(anexo.is_imagem
                                    ? [
                                          <Button
                                              key="preview"
                                              type="link"
                                              icon={<Eye />}
                                              onClick={() => handlePreview(anexo)}
                                          >
                                              Visualizar
                                          </Button>,
                                      ]
                                    : []),
                                <Button
                                    key="download"
                                    type="link"
                                    icon={<Download />}
                                    onClick={() => handleDownload(anexo)}
                                >
                                    Download
                                </Button>,
                                ...(podeExcluir
                                    ? [
                                          <Popconfirm
                                              key="delete"
                                              title="Excluir anexo"
                                              description="Tem certeza que deseja excluir este anexo?"
                                              onConfirm={() => handleDelete(anexo.id)}
                                              okText="Sim"
                                              cancelText="Não"
                                          >
                                              <Button type="link" danger icon={<Trash2 />}>
                                                  Excluir
                                              </Button>
                                          </Popconfirm>,
                                      ]
                                    : deleteDisabledReason
                                      ? [
                                            <Tooltip key="delete-hint" title={deleteDisabledReason}>
                                                <Button type="link" danger icon={<Trash2 />} disabled>
                                                    Excluir
                                                </Button>
                                            </Tooltip>,
                                        ]
                                      : []),
                            ]}
                        >
                            <List.Item.Meta
                                avatar={getFileIcon(anexo)}
                                title={
                                    <Space>
                                        <Text strong>{anexo.nome_original}</Text>
                                        {anexo.mime_type && !anexo.is_pdf && !anexo.is_imagem && (
                                            <Tag color="blue">
                                                {anexo.mime_type.split('/')[1]?.toUpperCase()}
                                            </Tag>
                                        )}
                                        {anexo.is_imagem && <Tag color="green">Imagem</Tag>}
                                        {anexo.is_pdf && <Tag color="red">PDF</Tag>}
                                    </Space>
                                }
                                description={
                                    <Space direction="vertical" size={0}>
                                        <Text type="secondary" style={{ fontSize: 12 }}>
                                            {anexo.tamanho_formatado ||
                                                formatarTamanho(anexo.tamanho)}
                                            {anexo.usuario &&
                                                ` • Enviado por ${anexo.usuario.nome}`}
                                            {` • ${formatDate(anexo.created_at, true)}`}
                                        </Text>
                                        {anexo.descricao && (
                                            <Text type="secondary" style={{ fontSize: 12 }}>
                                                {anexo.descricao}
                                            </Text>
                                        )}
                                    </Space>
                                }
                            />
                        </List.Item>
                        );
                    }}
                />
            )}

            <Image
                style={{ display: 'none' }}
                src={previewImage || ''}
                alt="Preview"
                preview={{
                    visible: !!previewImage,
                    src: previewImage || '',
                    onVisibleChange: (visible) => {
                        if (!visible) {
                            setPreviewImage(null);
                        }
                    },
                }}
            />
        </div>
    );
}
