/**
 * Approval Process Setup — List Page
 *
 * Approval Processes management with real operational data.
 * Route: /setup/approval-processes
 *
 * Features:
 * - PowerList with search, sort, row actions
 * - Object filter dropdown
 * - Activate/Deactivate toggle, Delete row actions
 * - Click process name → detail page
 */
import { getErrorMessage } from '@nexuscrm/host-sdk';
import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import {
    ChevronDown, ShieldCheck, Clock, Plus,
    ToggleRight, ToggleLeft, Trash2, Loader2, Edit,
} from 'lucide-react';
import { approvalsAPI } from '../../infrastructure/api/approvals';
import type { APIProcessDefinition, ProcessPendingCount } from './approvalTypes';
import { useSchemas } from '../../infrastructure/api/objectQueries';
import { formatDate } from '../../core/utils/formatting';
import { PowerList, PowerListColumn } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { Tooltip } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { ConfirmationModal } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { useSuccessToast, useErrorToast } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { tryGetSetupCapabilityPagePath } from '../../core/navigation/setupPagePaths';
import { OBJECT_APPROVAL_PROCESS_KEYS } from './useObjectHasApprovalProcess';
import { useApp } from '@nexuscrm/host-sdk';

// ============================================================================
// Component
// ============================================================================

export function ApprovalProcessSetup() {
    const navigate = useNavigate();
    const queryClient = useQueryClient();
    const { currentFrontendAppId } = useApp();
    const approvalProcessesPath = tryGetSetupCapabilityPagePath(currentFrontendAppId, 'approvalProcesses');
    const approvalProcessPath = (childPath: string) => (
        approvalProcessesPath ? `${approvalProcessesPath.replace(/\/$/, '')}/${childPath.replace(/^\//, '')}` : '/'
    );
    const { data: schemas = [] } = useSchemas();
    const showSuccess = useSuccessToast();
    const showError = useErrorToast();

    const [allProcesses, setAllProcesses] = useState<APIProcessDefinition[]>([]);
    const [pendingCounts, setPendingCounts] = useState<ProcessPendingCount[]>([]);
    const [loading, setLoading] = useState(true);
    const [selectedObject, setSelectedObject] = useState<string>('');
    const [dropdownOpen, setDropdownOpen] = useState(false);
    const dropdownRef = useRef<HTMLDivElement>(null);

    // Action state
    const [togglingId, setTogglingId] = useState<string | null>(null);
    const [deleteModalOpen, setDeleteModalOpen] = useState(false);
    const [processToDelete, setProcessToDelete] = useState<APIProcessDefinition | null>(null);
    const [deleting, setDeleting] = useState(false);

    const loadProcesses = useCallback(async () => {
        setLoading(true);
        try {
            const [data, counts] = await Promise.all([
                approvalsAPI.getApprovalProcesses(),
                approvalsAPI.getPendingCountsByProcess(),
            ]);
            setAllProcesses(data);
            setPendingCounts(counts);
        } catch {
            setAllProcesses([]);
            setPendingCounts([]);
        } finally {
            setLoading(false);
        }
    }, []);

    useEffect(() => { loadProcesses(); }, [loadProcesses]);

    // Click-outside to close dropdown
    useEffect(() => {
        const handleClickOutside = (e: MouseEvent) => {
            if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
                setDropdownOpen(false);
            }
        };
        if (dropdownOpen) document.addEventListener('mousedown', handleClickOutside);
        return () => document.removeEventListener('mousedown', handleClickOutside);
    }, [dropdownOpen]);

    // Derive unique objects from processes for the filter
    const objectOptions = useMemo(() => {
        const seen = new Set<string>();
        return allProcesses
            .map(p => p.TableEnumOrId)
            .filter(name => { if (seen.has(name)) return false; seen.add(name); return true; })
            .sort()
            .map(name => ({
                apiName: name,
                label: schemas.find(s => s.name === name)?.label || name,
            }));
    }, [allProcesses, schemas]);

    // Filter by selected object
    const filteredProcesses = useMemo(() =>
        selectedObject
            ? allProcesses.filter(p => p.TableEnumOrId === selectedObject)
            : allProcesses
        , [allProcesses, selectedObject]);

    const getObjectLabel = useCallback((apiName: string) => {
        const schema = schemas.find(s => s.name === apiName);
        return schema?.label || apiName;
    }, [schemas]);

    const getPendingCount = useCallback((processId: string) => {
        return pendingCounts.find(c => c.ProcessDefinitionId === processId)?.PendingCount ?? 0;
    }, [pendingCounts]);

    // Total pending across all visible processes
    const totalPending = useMemo(() => {
        return filteredProcesses.reduce((sum, p) => sum + getPendingCount(p.Id), 0);
    }, [filteredProcesses, getPendingCount]);

    // ── Actions ──

    const handleToggleStatus = async (process: APIProcessDefinition) => {
        setTogglingId(process.Id);
        try {
            if (process.State === 'Active') {
                await approvalsAPI.deactivateProcess(process.Id);
                showSuccess(`Deactivated "${process.Name}"`);
            } else {
                await approvalsAPI.activateProcess(process.Id);
                showSuccess(`Activated "${process.Name}"`);
            }
            loadProcesses();
        } catch (err: unknown) {
            showError(`Failed to toggle status: ${getErrorMessage(err)}`);
        } finally {
            setTogglingId(null);
            // Active-state may have flipped: re-derive the object-level
            // "has an active process" gates in every open consumer.
            queryClient.invalidateQueries({ queryKey: OBJECT_APPROVAL_PROCESS_KEYS.root });
        }
    };

    const confirmDelete = async () => {
        if (!processToDelete) return;
        setDeleting(true);
        try {
            // Safety: deactivate first if active
            if (processToDelete.State === 'Active') {
                await approvalsAPI.deactivateProcess(processToDelete.Id);
            }
            await approvalsAPI.deleteApprovalProcess(processToDelete.Id);
            showSuccess(`Deleted "${processToDelete.Name}"`);
            setDeleteModalOpen(false);
            setProcessToDelete(null);
            loadProcesses();
        } catch (err: unknown) {
            showError(`Failed to delete: ${getErrorMessage(err)}`);
        } finally {
            setDeleting(false);
            queryClient.invalidateQueries({ queryKey: OBJECT_APPROVAL_PROCESS_KEYS.root });
        }
    };

    // ── PowerList Columns ──

    const columns: PowerListColumn<APIProcessDefinition>[] = useMemo(() => [
        {
            key: 'Name',
            label: 'Process Name',
            minWidth: '240px',
            render: (_val, process) => (
                <div>
                    <div className="flex items-center gap-2">
                        <span className="font-medium text-slate-900 dark:text-white">{process.Name}</span>
                        <span className={`px-1.5 py-0.5 text-[10px] font-medium rounded ${process.State === 'Active'
                            ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
                            : 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400'
                            }`}>
                            {process.State}
                        </span>
                    </div>
                    {process.Description && (
                        <p className="text-xs text-gray-500 dark:text-gray-400 mt-0.5 line-clamp-1">{process.Description}</p>
                    )}
                </div>
            ),
        },
        {
            key: 'DeveloperName',
            label: 'API Name',
            minWidth: '160px',
            render: (val) => (
                <span className="font-mono text-xs text-slate-600 dark:text-gray-400">
                    {val ? String(val) : '—'}
                </span>
            ),
        },
        {
            key: 'TableEnumOrId',
            label: 'Object',
            minWidth: '120px',
            render: (val) => (
                <span className="bg-white dark:bg-gray-700 px-2 py-0.5 rounded shadow-sm border border-gray-100 dark:border-gray-600 text-xs font-medium text-gray-900 dark:text-gray-200">
                    {val ? getObjectLabel(String(val)) : '—'}
                </span>
            ),
        },
        {
            key: 'PendingCount' as keyof APIProcessDefinition & string,
            label: 'Pending',
            minWidth: '80px',
            sortable: false,
            render: (_val, process) => {
                const pending = getPendingCount(process.Id);
                return pending > 0 ? (
                    <span className="inline-flex items-center gap-1 text-xs font-semibold text-amber-600 dark:text-amber-400">
                        <Clock className="w-3 h-3" />
                        {pending}
                    </span>
                ) : (
                    <span className="text-xs text-gray-300 dark:text-gray-600">0</span>
                );
            },
        },
        {
            key: 'LastModifiedDate',
            label: 'Last Modified',
            minWidth: '110px',
            render: (val) => (
                <span className="text-xs text-slate-500 dark:text-gray-400">
                    {val ? formatDate(String(val)) : '—'}
                </span>
            ),
        },
        // Hidden column for search across descriptions
        {
            key: 'Description',
            label: 'Description',
            hidden: true,
            searchable: true,
            sortable: false,
        },
    ], [getObjectLabel, getPendingCount]);

    // ── Leading column: Activate/Deactivate toggle ──

    const renderLeading = (process: APIProcessDefinition) => (
        <Tooltip content={process.State === 'Active' ? 'Deactivate' : 'Activate'}>
            <button
                onClick={() => handleToggleStatus(process)}
                disabled={togglingId === process.Id}
                className={`p-1 rounded-lg transition-colors ${process.State === 'Active'
                    ? 'text-green-600 hover:bg-green-50 dark:hover:bg-green-900/20'
                    : 'text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700'
                    } disabled:opacity-50 disabled:cursor-not-allowed`}
            >
                {togglingId === process.Id ? (
                    <Loader2 className="w-4 h-4 animate-spin" />
                ) : process.State === 'Active' ? (
                    <ToggleRight className="w-4 h-4" />
                ) : (
                    <ToggleLeft className="w-4 h-4" />
                )}
            </button>
        </Tooltip>
    );

    // ── Row actions ──

    const renderActions = (process: APIProcessDefinition) => (
        <div className="flex items-center justify-end gap-1">
            <Tooltip content="Edit" position="top">
                <button
                    onClick={() => navigate(approvalProcessPath(`${process.Id}/edit`))}
                    className="p-1.5 text-gray-400 hover:text-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-lg transition-colors"
                >
                    <Edit className="w-4 h-4" />
                </button>
            </Tooltip>
            <Tooltip content="Delete" position="top">
                <button
                    onClick={() => { setProcessToDelete(process); setDeleteModalOpen(true); }}
                    className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors"
                >
                    <Trash2 className="w-4 h-4" />
                </button>
            </Tooltip>
        </div>
    );

    return (
        <div className="space-y-6">
            {/* Summary bar */}
            <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                    <div className="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
                        <span className="font-semibold">{filteredProcesses.length}</span>
                        <span>process{filteredProcesses.length !== 1 ? 'es' : ''}</span>
                        <span className="text-gray-300 dark:text-gray-600">|</span>
                        <span className="font-semibold text-green-600 dark:text-green-400">{filteredProcesses.filter(p => p.State === 'Active').length}</span>
                        <span>active</span>
                        {totalPending > 0 && (
                            <>
                                <span className="text-gray-300 dark:text-gray-600">|</span>
                                <span className="inline-flex items-center gap-1 text-amber-600 dark:text-amber-400 font-semibold">
                                    <Clock className="w-3.5 h-3.5" />
                                    {totalPending} pending
                                </span>
                            </>
                        )}
                    </div>
                </div>
                <button
                    onClick={() => navigate(approvalProcessPath('new'))}
                    className="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-semibold rounded-lg transition-colors shadow-sm"
                >
                    <Plus className="w-4 h-4" />
                    New Approval Process
                </button>
            </div>

            {/* Object Filter */}
            <div className="flex items-center gap-3">
                <span className="text-sm font-medium text-gray-700 dark:text-gray-300">
                    Manage Approval Processes For:
                </span>
                <div className="relative" ref={dropdownRef}>
                    <button
                        onClick={() => setDropdownOpen(!dropdownOpen)}
                        className="flex items-center gap-2 px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-medium text-gray-900 dark:text-white hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors min-w-[200px] justify-between"
                    >
                        {selectedObject ? getObjectLabel(selectedObject) : 'All Objects'}
                        <ChevronDown className={`w-4 h-4 text-gray-400 transition-transform ${dropdownOpen ? 'rotate-180' : ''}`} />
                    </button>
                    {dropdownOpen && (
                        <div className="absolute z-20 mt-1 w-full bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg max-h-64 overflow-y-auto">
                            <button
                                onClick={() => { setSelectedObject(''); setDropdownOpen(false); }}
                                className={`w-full text-left px-4 py-2 text-sm hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors ${!selectedObject ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-400 font-medium' : 'text-gray-700 dark:text-gray-300'}`}
                            >
                                All Objects
                            </button>
                            {objectOptions.map(opt => (
                                <button
                                    key={opt.apiName}
                                    onClick={() => { setSelectedObject(opt.apiName); setDropdownOpen(false); }}
                                    className={`w-full text-left px-4 py-2 text-sm hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors ${selectedObject === opt.apiName ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-400 font-medium' : 'text-gray-700 dark:text-gray-300'}`}
                                >
                                    {opt.label}
                                </button>
                            ))}
                        </div>
                    )}
                </div>
            </div>

            {/* PowerList */}
            <PowerList<APIProcessDefinition>
                data={filteredProcesses}
                columns={columns}
                loading={loading}
                rowKey={(p) => p.Id}
                onRowClick={(p) => navigate(approvalProcessPath(p.Id))}
                searchable
                searchPlaceholder="Search approval processes..."
                defaultSort={{ key: 'Name', direction: 'asc' }}
                emptyIcon={<ShieldCheck className="w-12 h-12" />}
                emptyTitle="No Approval Processes"
                emptyMessage={
                    selectedObject
                        ? `No approval processes found for ${getObjectLabel(selectedObject)}.`
                        : 'No approval processes defined in this org.'
                }
                emptyAction={{ label: 'New Approval Process', onClick: () => navigate(approvalProcessPath('new')) }}
                leadingColumn={{ width: '44px', render: renderLeading }}
                actions={renderActions}
                ariaLabel="Approval processes list"
            />

            {/* Delete Confirmation Modal */}
            <ConfirmationModal
                isOpen={deleteModalOpen}
                onClose={() => { setDeleteModalOpen(false); setProcessToDelete(null); }}
                onConfirm={confirmDelete}
                title="Delete Approval Process"
                message={`Are you sure you want to delete "${processToDelete?.Name}"? This action cannot be undone.${processToDelete?.State === 'Active' ? ' The process will be deactivated first.' : ''
                    }`}
                confirmLabel="Delete"
                cancelLabel="Cancel"
                variant="danger"
                loading={deleting}
            />
        </div>
    );
}

export default ApprovalProcessSetup;
