import React, { useEffect, useState, useCallback, useMemo, useRef } from 'react';
import { getErrorMessage } from '@nexuscrm/host-sdk';
import { dataAPI } from '../infrastructure/api/data';
import { Trash2, RotateCcw, Filter, CheckSquare, Square, AlertTriangle } from 'lucide-react';
import { useSuccessToast, useErrorToast } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { ConfirmationModal } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { useSystemPermission } from '@nexuscrm/host-sdk';
import type { RecycleBinItem } from '../types';
import { PowerList, type PowerListColumn } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { useSchemas } from '../infrastructure/api/objectQueries';

export const RecycleBin: React.FC = () => {
    const [items, setItems] = useState<RecycleBinItem[]>([]);
    const [loading, setLoading] = useState(true);
    // Object API names whose server-side query failed; when non-empty the
    // list is incomplete and we warn the user rather than letting a partial
    // result read as complete (#1681 / #1738 P2).
    const [failedObjects, setFailedObjects] = useState<string[]>([]);
    const showSuccess = useSuccessToast();
    const showError = useErrorToast();
    const { data: schemas = [] } = useSchemas();
    const canViewAllData = useSystemPermission('ViewAllData');
    const canModifyAllData = useSystemPermission('ModifyAllData');
    const canViewOrgRecycleBin = canViewAllData || canModifyAllData;
    const abortRef = useRef(false);

    // Filter State
    const [scope, setScope] = useState<'mine' | 'all'>('mine');

    // Selection State
    const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());

    // Confirmation logic
    const [action, setAction] = useState<'restore' | 'purge' | null>(null);
    const [processing, setProcessing] = useState(false);

    // Helper to get object label from schema metadata
    const getObjectLabel = useCallback((apiName: string) => {
        if (!apiName) return '';
        const schema = schemas.find(s => (s.name || '').toLowerCase() === apiName.toLowerCase());
        return schema?.label || apiName;
    }, [schemas]);

    const load = useCallback(async () => {
        setLoading(true);
        setItems([]);
        setFailedObjects([]);
        setSelectedIds(new Set());
        abortRef.current = false;

        try {
            const result = await dataAPI.getRecycleBinItems(scope);
            if (!abortRef.current) {
                setItems(result.items);
                setFailedObjects(
                    result.partialFailure
                        ? result.failedObjects.map(f => f.objectApiName)
                        : [],
                );
            }
        } catch (err: unknown) {
            showError(getErrorMessage(err, "Could not load recycle bin items"));
        } finally {
            if (!abortRef.current) {
                setLoading(false);
            }
        }
    }, [scope, showError]);

    useEffect(() => {
        load();
        return () => { abortRef.current = true; };
    }, [load]);

    // ── Selection handlers ──
    const handleSelectOne = (id: string) => {
        setSelectedIds(prev => {
            const next = new Set(prev);
            if (next.has(id)) next.delete(id);
            else next.add(id);
            return next;
        });
    };

    // ── Action handlers ──
    const handleExecute = async () => {
        if (!action) return;
        setProcessing(true);
        try {
            const ids = Array.from(selectedIds);
            const promises = ids.map(id =>
                action === 'restore' ? dataAPI.restoreRecord(id) : dataAPI.purgeRecord(id)
            );
            await Promise.all(promises);
            showSuccess(`Successfully processed ${ids.length} record${ids.length !== 1 ? 's' : ''}.`);
            await load();
            setAction(null);
        } catch (err: unknown) {
            showError(getErrorMessage(err, 'Operation failed'));
        } finally {
            setProcessing(false);
        }
    };

    // ── PowerList columns ──
    const columns = useMemo<PowerListColumn<RecycleBinItem>[]>(() => [
        {
            key: 'RecordName',
            label: 'Name',
            minWidth: '200px',
            render: (val) => (
                <span className="font-medium text-gray-900 dark:text-gray-100">{val as string || '—'}</span>
            ),
        },
        {
            key: 'ObjectApiName',
            label: 'Object',
            width: '180px',
            render: (val) => (
                <span className="inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300">
                    {getObjectLabel(val as string)}
                </span>
            ),
        },
        {
            key: 'DeletedDate',
            label: 'Deleted Date',
            width: '180px',
            render: (val) => {
                if (!val) return '—';
                return new Date(val as string).toLocaleString();
            },
        },
        {
            key: 'DeletedBy',
            label: 'Deleted By',
            width: '160px',
        },
    ], [getObjectLabel]);

    return (
        <div className="max-w-7xl mx-auto p-6">
            {/* Header */}
            <div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6">
                <div>
                    <h1 className="text-2xl font-bold text-gray-800 dark:text-gray-100 flex items-center gap-2">
                        <Trash2 className="text-gray-500" /> Recycle Bin
                    </h1>
                    <p className="text-gray-500 dark:text-gray-400 text-sm mt-1">Manage deleted records.</p>
                </div>

                <div className="flex items-center gap-3">
                    {/* Scope Filter */}
                    <div className="relative">
                        <select
                            value={scope}
                            onChange={e => setScope(e.target.value as 'mine' | 'all')}
                            className="appearance-none bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 py-2 pl-4 pr-10 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent font-medium text-sm"
                        >
                            <option value="mine">My Recycle Bin</option>
                            <option value="all" disabled={!canViewOrgRecycleBin}>
                                Org Recycle Bin {!canViewOrgRecycleBin && '(Requires View All Data)'}
                            </option>
                        </select>
                        <Filter size={16} className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none" />
                    </div>

                    {/* Bulk action buttons */}
                    {selectedIds.size > 0 && (
                        <>
                            <button
                                onClick={() => setAction('restore')}
                                className="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center gap-2 hover:bg-blue-700 transition-colors font-medium text-sm shadow-sm"
                            >
                                <RotateCcw size={16} /> Restore ({selectedIds.size})
                            </button>
                            <button
                                onClick={() => setAction('purge')}
                                className="px-4 py-2 bg-white dark:bg-gray-800 border border-red-200 dark:border-red-800 text-red-600 dark:text-red-400 rounded-lg flex items-center gap-2 hover:bg-red-50 dark:hover:bg-red-950 transition-colors font-medium text-sm"
                            >
                                <Trash2 size={16} /> Delete ({selectedIds.size})
                            </button>
                        </>
                    )}
                </div>
            </div>

            {/* Partial-failure banner: some object types could not be loaded,
                so the list below is incomplete. (#1681 / #1738 P2) */}
            {!loading && failedObjects.length > 0 && (
                <div
                    role="alert"
                    className="mb-4 flex items-start gap-2 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-950 px-4 py-3 text-sm text-amber-800 dark:text-amber-200"
                >
                    <AlertTriangle size={16} className="mt-0.5 shrink-0" />
                    <span>
                        Some object types could not be loaded, so this list may be incomplete:{' '}
                        {failedObjects.map(getObjectLabel).join(', ')}. Try refreshing; if the
                        problem persists, contact your administrator.
                    </span>
                </div>
            )}

            {/* PowerList table */}
            <PowerList<RecycleBinItem>
                data={items}
                columns={columns}
                loading={loading}
                rowKey={row => row.Id}
                searchable
                searchPlaceholder="Search deleted records..."
                emptyIcon={<Trash2 size={48} />}
                emptyTitle="Recycle bin is empty"
                emptyMessage="No deleted records found."
                defaultSort={{ key: 'DeletedDate', direction: 'desc' }}
                ariaLabel="Recycle Bin"
                leadingColumn={{
                    width: '44px',
                    render: (row) => (
                        <button
                            onClick={() => handleSelectOne(row.RecordId)}
                            className={`transition-colors ${selectedIds.has(row.RecordId)
                                ? 'text-blue-600'
                                : 'text-gray-300 dark:text-gray-600 hover:text-gray-400 dark:hover:text-gray-500'
                                }`}
                        >
                            {selectedIds.has(row.RecordId) ? <CheckSquare size={18} /> : <Square size={18} />}
                        </button>
                    ),
                }}
                actions={(row) => (
                    <div className="flex items-center gap-1 justify-end opacity-0 group-hover:opacity-100 transition-opacity">
                        <button
                            onClick={() => { setSelectedIds(new Set([row.RecordId])); setAction('restore'); }}
                            className="p-1.5 text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-950 rounded-md transition-colors"
                            title="Restore"
                        >
                            <RotateCcw size={15} />
                        </button>
                        <button
                            onClick={() => { setSelectedIds(new Set([row.RecordId])); setAction('purge'); }}
                            className="p-1.5 text-red-500 hover:bg-red-50 dark:hover:bg-red-950 rounded-md transition-colors"
                            title="Delete permanently"
                        >
                            <Trash2 size={15} />
                        </button>
                    </div>
                )}
            />

            {/* Confirmation modal */}
            <ConfirmationModal
                isOpen={!!action}
                onClose={() => setAction(null)}
                onConfirm={handleExecute}
                title={action === 'restore' ? 'Restore Records' : 'Permanent Delete'}
                message={action === 'restore'
                    ? `Are you sure you want to restore ${selectedIds.size} selected record(s)?`
                    : `Are you sure you want to permanently delete ${selectedIds.size} record(s)? This cannot be undone.`
                }
                confirmLabel={action === 'restore' ? 'Restore' : 'Delete Forever'}
                cancelLabel="Cancel"
                variant={action === 'purge' ? 'danger' : 'info'}
                loading={processing}
            />
        </div>
    );
};
