'use client';

import { Alert, Button, Space } from 'antd';
import type { FormInstance } from 'antd/es/form';
import dayjs from 'dayjs';
import { useCallback, useEffect, useRef, useState } from 'react';
import { FORM_DRAFT_STORAGE_PREFIX } from '@/lib/forms/formDraftConstants';

const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000;
const DEFAULT_DEBOUNCE_MS = 900;

/** Exclui nomes de campo com dados tipicamente sensíveis do snapshot local (Task 127). */
const SENSITIVE_FIELD_NAME = /(password|senha|token|cpf|cnpj|cartao|cvv|secret|pix)/i;

type DraftEnvelope = { savedAt: number; values: Record<string, unknown> };

function stripSensitiveKeys(values: Record<string, unknown>): Record<string, unknown> {
    const out: Record<string, unknown> = {};
    for (const [k, v] of Object.entries(values)) {
        if (SENSITIVE_FIELD_NAME.test(k)) continue;
        out[k] = v;
    }
    return out;
}

function serializeForStorage(values: Record<string, unknown>): Record<string, unknown> {
    const raw = stripSensitiveKeys(values);
    const out: Record<string, unknown> = {};
    for (const [k, v] of Object.entries(raw)) {
        if (v == null) {
            out[k] = v;
            continue;
        }
        if (dayjs.isDayjs(v)) {
            out[k] = { __wqDayjs: true, iso: v.format('YYYY-MM-DD') };
            continue;
        }
        out[k] = v;
    }
    return out;
}

function deserializeFromStorage(raw: Record<string, unknown>): Record<string, unknown> {
    const out: Record<string, unknown> = {};
    for (const [k, v] of Object.entries(raw)) {
        if (v && typeof v === 'object' && '__wqDayjs' in v) {
            const iso = (v as unknown as { iso?: unknown }).iso;
            if (typeof iso === 'string') {
                out[k] = dayjs(iso);
                continue;
            }
        }
        out[k] = v;
    }
    return out;
}

export interface UseAntdFormDraftAutosaveOptions {
    ttlMs?: number;
    debounceMs?: number;
    enabled?: boolean;
    /** Chamado após `setFieldsValue` na restauração (ex.: sincronizar estado React com o formulário). */
    onAfterRestore?: () => void;
}

/**
 * Rascunho local (debounce) + prompt de recuperação. Não substitui validação server-side.
 */
export function useAntdFormDraftAutosave(
    form: FormInstance,
    draftId: string,
    options?: UseAntdFormDraftAutosaveOptions
) {
    const ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
    const debounceMs = options?.debounceMs ?? DEFAULT_DEBOUNCE_MS;
    const enabled = options?.enabled ?? true;
    const onAfterRestore = options?.onAfterRestore;
    const storageKey = `${FORM_DRAFT_STORAGE_PREFIX}${draftId}`;

    const [prompt, setPrompt] = useState(false);
    const [lastSavedAt, setLastSavedAt] = useState<number | null>(null);
    const skipSaveRef = useRef(false);
    const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

    const clearDraft = useCallback(() => {
        if (typeof window === 'undefined') return;
        try {
            window.localStorage.removeItem(storageKey);
        } catch {
            // noop
        }
        setLastSavedAt(null);
    }, [storageKey]);

    const persist = useCallback(() => {
        if (!enabled || typeof window === 'undefined') return;
        try {
            const values = form.getFieldsValue(true) as Record<string, unknown>;
            const envelope: DraftEnvelope = {
                savedAt: Date.now(),
                values: serializeForStorage(values),
            };
            window.localStorage.setItem(storageKey, JSON.stringify(envelope));
            setLastSavedAt(envelope.savedAt);
        } catch {
            // quota / privado
        }
    }, [enabled, form, storageKey]);

    useEffect(() => {
        if (!enabled || typeof window === 'undefined') return;
        try {
            const raw = window.localStorage.getItem(storageKey);
            if (!raw) return;
            const parsed = JSON.parse(raw) as DraftEnvelope;
            if (!parsed?.values || typeof parsed.savedAt !== 'number') return;
            if (Date.now() - parsed.savedAt > ttlMs) {
                window.localStorage.removeItem(storageKey);
                return;
            }
            setPrompt(true);
        } catch {
            try {
                window.localStorage.removeItem(storageKey);
            } catch {
                // noop
            }
        }
    }, [enabled, storageKey, ttlMs]);

    const restoreDraft = useCallback(() => {
        if (typeof window === 'undefined') return;
        try {
            const raw = window.localStorage.getItem(storageKey);
            if (!raw) {
                setPrompt(false);
                return;
            }
            const parsed = JSON.parse(raw) as DraftEnvelope;
            skipSaveRef.current = true;
            form.setFieldsValue(deserializeFromStorage(parsed.values ?? {}));
            skipSaveRef.current = false;
            setLastSavedAt(parsed.savedAt);
            onAfterRestore?.();
        } catch {
            // noop
        }
        setPrompt(false);
    }, [form, onAfterRestore, storageKey]);

    const dismissPrompt = useCallback(() => {
        clearDraft();
        setPrompt(false);
    }, [clearDraft]);

    const schedulePersist = useCallback(() => {
        if (!enabled || skipSaveRef.current) return;
        if (timerRef.current) clearTimeout(timerRef.current);
        timerRef.current = setTimeout(() => {
            persist();
            timerRef.current = null;
        }, debounceMs);
    }, [debounceMs, enabled, persist]);

    useEffect(() => {
        return () => {
            if (timerRef.current) clearTimeout(timerRef.current);
        };
    }, []);

    const draftBanner =
        prompt && enabled ? (
            <Alert
                type="warning"
                showIcon
                style={{ marginBottom: 16 }}
                message="Rascunho encontrado"
                description="Há um preenchimento salvo neste dispositivo. Restaure ou descarte antes de continuar."
                action={
                    <Space direction="vertical" size="small">
                        <Button size="small" type="primary" onClick={restoreDraft}>
                            Restaurar rascunho
                        </Button>
                        <Button size="small" onClick={dismissPrompt}>
                            Descartar
                        </Button>
                    </Space>
                }
            />
        ) : null;

    const savedHint =
        lastSavedAt && enabled && !prompt ? (
            <div
                style={{ marginBottom: 12, color: 'var(--text-secondary)', fontSize: 12 }}
                role="status"
                aria-live="polite"
            >
                Rascunho salvo automaticamente neste dispositivo.
            </div>
        ) : null;

    return {
        draftBanner,
        savedHint,
        onValuesChange: schedulePersist,
        clearDraft,
    };
}
