/**
 * Approval Process Detail Page
 *
 * Full detail view of a single Approval Process with real operational data.
 * Route: /setup/approval-processes/:processId
 *
 * Sections:
 * - Process Definition Detail (PropRow layout)
 * - Approval Steps table
 * - Recent Approval Activity (real ProcessInstance data)
 * - Process Statistics
 */
import { getErrorMessage } from '@nexuscrm/host-sdk';
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import {
    ArrowLeft, Loader2, AlertCircle, CheckCircle, XCircle,
    ListOrdered, Activity, Clock, Play, BarChart2, Zap, Trash2, Edit, Copy as CopyIcon,
} from 'lucide-react';
import { approvalsAPI } from '../../infrastructure/api/approvals';
import type { APIProcessDefinition, APIProcessNode, APIProcessAction, RecentProcessInstance } from './approvalTypes';
import { useSchemas } from '../../infrastructure/api/objectQueries';
import { ProcessActionsSection } from './components/ProcessActionsSection';
import { formatDate } from '../../core/utils/formatting';
import { PropRow } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { ROUTES } from '../../core/constants/Routes';
import { PROCESS_STATUS } from './approvalConstants';
import { ConfirmationModal } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { Badge } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { formatAllowedSubmitters, parseApprovalProcessConfiguration } from './utils/approvalProcessMetadata';
import { useDisplaySteps } from './hooks/useDisplaySteps';
import { useProcessActions } from './hooks/useProcessActions';
import { ProcessCloneModal } from './components/ProcessCloneModal';
import { tryGetSetupCapabilityPagePath } from '../../core/navigation/setupPagePaths';
import { useApp } from '@nexuscrm/host-sdk';

// ============================================================================
// Helpers
// ============================================================================

/** Parse EntryFilter which may be JSON (legacy SF sync) or a plain formula string */
function parseEntryFilter(raw: string): string {
    const trimmed = raw.trim();
    if (trimmed.startsWith('{')) {
        try {
            const parsed = JSON.parse(trimmed);
            return parsed.formula || trimmed;
        } catch {
            return trimmed;
        }
    }
    return trimmed;
}

// ============================================================================
// Main Component
// ============================================================================

export function ApprovalProcessDetailPage() {
    const { processId } = useParams<{ processId: string }>();
    const { data: schemas = [] } = useSchemas();
    const navigate = useNavigate();
    const { currentFrontendAppId } = useApp();
    const approvalProcessesPath = tryGetSetupCapabilityPagePath(currentFrontendAppId, 'approvalProcesses') ?? '/';
    const approvalProcessChildPath = (childPath: string) => (
        approvalProcessesPath === '/' ? '/' : `${approvalProcessesPath.replace(/\/$/, '')}/${childPath.replace(/^\//, '')}`
    );

    const [process, setProcess] = useState<APIProcessDefinition | null>(null);
    const [steps, setSteps] = useState<APIProcessNode[]>([]);
    const [actions, setActions] = useState<APIProcessAction[]>([]);
    const [recentActivity, setRecentActivity] = useState<RecentProcessInstance[]>([]);
    const [pendingCount, setPendingCount] = useState(0);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    const hasLoadedRef = useRef(false);

    const loadDetail = useCallback(async () => {
        if (!processId) return;
        if (!hasLoadedRef.current) setLoading(true);
        setError(null);
        try {
            const [proc, stepsData, actionsData, activity, pendingCounts] = await Promise.all([
                approvalsAPI.getApprovalProcessDetail(processId),
                approvalsAPI.getProcessNodes(processId),
                approvalsAPI.getProcessActions(processId),
                approvalsAPI.getRecentActivityForProcess(processId, 15),
                approvalsAPI.getPendingCountsByProcess(),
            ]);
            if (!proc) {
                setError('Approval process not found.');
                return;
            }
            setProcess(proc);
            // Resolve approver display names from usernames
            const usernamesToResolve = stepsData
                .filter(s => !s.ApproverUser?.Name && s.ApproverUserId && s.ApproverUserId.includes('@'))
                .map(s => s.ApproverUserId!);
            if (usernamesToResolve.length > 0) {
                try {
                    const unique = [...new Set(usernamesToResolve)];
                    const resp = await approvalsAPI.getUsersByUsernames(unique);
                    const nameMap = new Map(resp.map(u => [u.Username, [u.FirstName, u.LastName].filter(Boolean).join(' ')]));
                    for (const step of stepsData) {
                        if (!step.ApproverUser?.Name && step.ApproverUserId && nameMap.has(step.ApproverUserId)) {
                            step.ApproverUser = { ...(step.ApproverUser || {}), Name: nameMap.get(step.ApproverUserId) };
                        }
                    }
                } catch { /* best-effort */ }
            }
            setSteps(stepsData);
            setActions(actionsData);
            setRecentActivity(activity);
            const myCount = pendingCounts.find(c => c.ProcessDefinitionId === processId);
            setPendingCount(myCount?.PendingCount ?? 0);
            hasLoadedRef.current = true;
        } catch (err: unknown) {
            setError(getErrorMessage(err, 'Failed to load approval process.'));
        } finally {
            setLoading(false);
        }
    }, [processId]);

    useEffect(() => {
        if (!processId) return;
        loadDetail();
    }, [processId, loadDetail]);

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

    // Compute stats from recent activity
    const stats = useMemo(() => {
        const approved = recentActivity.filter(a => a.Status === PROCESS_STATUS.APPROVED).length;
        const rejected = recentActivity.filter(a => a.Status === PROCESS_STATUS.REJECTED).length;
        const pending = recentActivity.filter(a => a.Status === PROCESS_STATUS.PENDING).length;
        return { approved, rejected, pending, total: recentActivity.length };
    }, [recentActivity]);

    const metadataConfiguration = useMemo(() => parseApprovalProcessConfiguration(process?.Metadata), [process?.Metadata]);
    const metadataSteps = metadataConfiguration.approvalSteps;
    const allowedSubmitterLabels = useMemo(() => formatAllowedSubmitters(
        metadataConfiguration.hasExplicitAllowedSubmitters
            ? metadataConfiguration.allowedSubmitters
            : [{ type: 'allInternalUsers' }]
    ), [metadataConfiguration]);

    const displaySteps = useDisplaySteps(steps, metadataSteps);
    const stepCount = displaySteps.length;
    const metadataFallbackActive = steps.length === 0 && metadataSteps.length > 0;

    const processActions = useProcessActions(processId, process, loadDetail);

    const handleToggleActive = async () => {
        const newState = await processActions.handleToggleActive();
        if (newState) {
            setProcess(prev => prev ? { ...prev, State: newState } : prev);
        }
    };

    // Loading
    if (loading) {
        return (
            <div className="flex items-center justify-center py-24">
                <Loader2 className="w-6 h-6 animate-spin text-blue-600" />
                <span className="ml-3 text-gray-500 dark:text-gray-400">Loading approval process…</span>
            </div>
        );
    }

    // Error
    if (error || !process) {
        return (
            <div className="max-w-3xl mx-auto py-12">
                <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-6 flex items-start gap-3">
                    <AlertCircle className="w-5 h-5 text-red-600 dark:text-red-400 mt-0.5 shrink-0" />
                    <div>
                        <h3 className="font-semibold text-red-800 dark:text-red-300">Failed to load approval process</h3>
                        <p className="text-sm text-red-700 dark:text-red-400 mt-1">{error || 'Process not found.'}</p>
                        <Link to={approvalProcessesPath} className="inline-flex items-center gap-1 text-sm text-blue-600 hover:underline mt-3">
                            <ArrowLeft className="w-4 h-4" /> Back to Approval Processes
                        </Link>
                    </div>
                </div>
            </div>
        );
    }

    const isActive = process.State === 'Active';

    return (
        <div className="space-y-6">
            {/* Header */}
            <div className="flex items-start justify-between">
                <div>
                    <p className="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase tracking-wider mb-1">
                        Approval Process
                    </p>
                    <h1 className="text-xl font-bold text-gray-900 dark:text-white">
                        {process.Name}
                    </h1>
                    <Link
                        to={approvalProcessesPath}
                        className="inline-flex items-center gap-1 text-sm text-blue-600 hover:underline mt-1"
                    >
                        <ArrowLeft className="w-3.5 h-3.5" />
                        &laquo; Back to List: Approval Processes
                    </Link>
                </div>
                {/* Quick actions */}
                <div className="flex items-center gap-2">
                    {/* Activate / Deactivate */}
                    <button
                        onClick={handleToggleActive}
                        className={`inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors ${isActive
                            ? 'bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:border-red-400 hover:text-red-600'
                            : 'bg-green-600 text-white hover:bg-green-700'
                            }`}
                    >
                        <Zap className="w-4 h-4" />
                        {isActive ? 'Deactivate' : 'Activate'}
                    </button>
                    <button
                        onClick={() => navigate(approvalProcessChildPath(`${processId}/edit`))}
                        className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:border-blue-400 hover:text-blue-600"
                    >
                        <Edit className="w-4 h-4" />
                        Edit
                    </button>
                    {/* Go to records */}
                    {isActive && (
                        <button
                            onClick={() => navigate(ROUTES.OBJECT.LIST(process.TableEnumOrId))}
                            className="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors"
                        >
                            <Play className="w-4 h-4" />
                            Go to {getObjectLabel(process.TableEnumOrId)} Records
                        </button>
                    )}
                    {/* Clone */}
                    <button
                        onClick={processActions.openCloneModal}
                        className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors bg-purple-600 text-white hover:bg-purple-700"
                    >
                        <CopyIcon className="w-4 h-4" />
                        Clone
                    </button>
                    {/* Delete */}
                    <button
                        onClick={() => processActions.setDeleteModalOpen(true)}
                        className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:border-red-400 hover:text-red-600"
                    >
                        <Trash2 className="w-4 h-4" />
                        Delete
                    </button>
                </div>
            </div>

            {/* Stats Cards */}
            <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
                <StatCard
                    label="Pending"
                    value={pendingCount}
                    icon={<Clock className="w-4 h-4" />}
                    color="amber"
                />
                <StatCard
                    label="Approved (Recent)"
                    value={stats.approved}
                    icon={<CheckCircle className="w-4 h-4" />}
                    color="green"
                />
                <StatCard
                    label="Rejected (Recent)"
                    value={stats.rejected}
                    icon={<XCircle className="w-4 h-4" />}
                    color="red"
                />
                <StatCard
                    label="Steps"
                    value={stepCount}
                    icon={<ListOrdered className="w-4 h-4" />}
                    color="blue"
                />
            </div>

            {/* Process Definition Detail */}
            <div className="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm">
                <div className="flex items-center justify-between px-5 py-3 border-b border-gray-200 dark:border-gray-700">
                    <h2 className="text-base font-semibold text-gray-800 dark:text-gray-200">Process Definition Detail</h2>
                </div>

                <div className="px-5 py-4 overflow-x-auto">
                    <table className="w-full">
                        <tbody>
                            <PropRow
                                left={{ label: 'Process Name', value: process.Name }}
                                right={{
                                    label: 'Active',
                                    value: (
                                        <Badge variant={isActive ? 'success' : 'neutral'} icon={isActive ? <CheckCircle className="w-3.5 h-3.5" /> : <XCircle className="w-3.5 h-3.5" />}>
                                            {isActive ? 'Yes' : 'No'}
                                        </Badge>
                                    ),
                                }}
                            />
                            <PropRow
                                left={{
                                    label: 'Unique Name',
                                    value: <span className="font-mono text-xs">{process.DeveloperName || '—'}</span>,
                                }}
                                right={{
                                    label: 'Object',
                                    value: (
                                        <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">
                                            {getObjectLabel(process.TableEnumOrId)}
                                        </span>
                                    ),
                                }}
                            />
                            <PropRow
                                left={{
                                    label: 'Description',
                                    value: process.Description || '—',
                                }}
                                right={{
                                    label: 'Record Editability',
                                    value: process.LockType ? (
                                        <span className="text-sm">
                                            {process.LockType === 'Admin' ? 'Administrator Only' :
                                                process.LockType === 'WorkItem' ? 'Administrator OR Current Approver' :
                                                    process.LockType}
                                        </span>
                                    ) : '—',
                                }}
                            />
                            <PropRow
                                left={{
                                    label: 'Entry Criteria',
                                    value: process.EntryFilter ? (
                                        <span className="font-mono text-xs bg-gray-50 dark:bg-gray-700 px-2 py-1 rounded">{parseEntryFilter(process.EntryFilter)}</span>
                                    ) : '—',
                                }}
                                right={{
                                    label: 'Allow Recall',
                                    value: process.AllowRecall ? 'Yes' : 'No',
                                }}
                            />
                            <PropRow
                                left={{
                                    label: 'Allowed Submitters',
                                    value: allowedSubmitterLabels.length > 0 ? allowedSubmitterLabels.join(', ') : '—',
                                }}
                            />
                            <PropRow
                                left={{
                                    label: 'Created By',
                                    value: process.CreatedBy?.Name ? (
                                        <div className="flex flex-col text-xs">
                                            <span>{process.CreatedBy.Name}</span>
                                            <span className="text-gray-400 dark:text-gray-500">{process.CreatedDate ? formatDate(process.CreatedDate) : '—'}</span>
                                        </div>
                                    ) : '—',
                                }}
                                right={{
                                    label: 'Last Modified By',
                                    value: process.LastModifiedBy?.Name ? (
                                        <div className="flex flex-col text-xs">
                                            <span>{process.LastModifiedBy.Name}</span>
                                            <span className="text-gray-400 dark:text-gray-500">{process.LastModifiedDate ? formatDate(process.LastModifiedDate) : '—'}</span>
                                        </div>
                                    ) : '—',
                                }}
                            />
                        </tbody>
                    </table>
                </div>
            </div>

            {metadataFallbackActive && (
                <div className="bg-amber-50 dark:bg-amber-900/10 border border-amber-200 dark:border-amber-800 rounded-xl shadow-sm">
                    <div className="px-5 py-3 border-b border-amber-200 dark:border-amber-800">
                        <h2 className="text-base font-semibold text-amber-900 dark:text-amber-200">Approval Steps</h2>
                        <p className="text-xs text-amber-700 dark:text-amber-300 mt-1">
                            Showing step definitions from process metadata because ProcessNode records are currently unavailable.
                        </p>
                    </div>
                    <div className="divide-y divide-amber-100 dark:divide-amber-800/50">
                        {displaySteps.map((step) => (
                            <div key={step.key} className="px-5 py-4">
                                <div className="flex items-start justify-between gap-4">
                                    <div>
                                        <div className="flex items-center gap-2">
                                            <span className="inline-flex items-center justify-center w-5 h-5 bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 text-xs font-bold rounded-full">
                                                {step.index}
                                            </span>
                                            <span className="text-sm font-medium text-gray-900 dark:text-white">{step.name}</span>
                                        </div>
                                        <p className="text-xs text-gray-500 dark:text-gray-400 mt-2">{step.description}</p>
                                    </div>
                                    <div className="text-right text-xs text-gray-500 dark:text-gray-400">
                                        <div>{step.approvers.length > 0 ? step.approvers.join(', ') : 'No approvers'}</div>
                                        {step.approvalMode && <div className="mt-1">{step.approvalMode}</div>}
                                    </div>
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            )}

            {/* Process Actions & Steps (unified execution-order view) */}
            <ProcessActionsSection
                mode="readOnly"
                processDefinitionId={processId!}
                actions={actions}
                steps={steps}
                displaySteps={displaySteps}
                finalApprovalRecordLock={process?.FinalApprovalRecordLock ?? false}
                finalRejectionRecordLock={process?.FinalRejectionRecordLock ?? false}
                onRequestEdit={() => navigate(approvalProcessChildPath(`${processId}/edit`))}
            />

            {/* Recent Approval Activity */}
            <div className="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm">
                <div className="flex items-center justify-between px-5 py-3 border-b border-gray-200 dark:border-gray-700">
                    <h2 className="text-base font-semibold text-gray-800 dark:text-gray-200 flex items-center gap-2">
                        <Activity className="w-4 h-4 text-gray-400" />
                        Recent Approval Activity
                    </h2>
                    <span className="text-xs text-gray-400">{recentActivity.length} recent instance{recentActivity.length !== 1 ? 's' : ''}</span>
                </div>

                {recentActivity.length > 0 ? (
                    <div className="overflow-x-auto">
                        <table className="w-full text-sm">
                            <thead>
                                <tr className="bg-gray-50 dark:bg-gray-700/30 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                                    <th className="px-4 py-2.5">Status</th>
                                    <th className="px-4 py-2.5">Record ID</th>
                                    <th className="px-4 py-2.5">Submitted By</th>
                                    <th className="px-4 py-2.5">Submitted</th>
                                    <th className="px-4 py-2.5">Completed</th>
                                </tr>
                            </thead>
                            <tbody>
                                {recentActivity.map(inst => (
                                    <tr key={inst.Id} className="border-b border-gray-100 dark:border-gray-700/50 hover:bg-gray-50 dark:hover:bg-gray-700/20 transition-colors">
                                        <td className="px-4 py-2.5">
                                            <StatusBadge status={inst.Status} />
                                        </td>
                                        <td className="px-4 py-2.5">
                                            <button
                                                className="font-mono text-xs text-blue-600 hover:underline"
                                                onClick={() => navigate(ROUTES.OBJECT.DETAIL(process.TableEnumOrId, inst.TargetObjectId))}
                                            >
                                                {inst.TargetObjectId}
                                            </button>
                                        </td>
                                        <td className="px-4 py-2.5 text-gray-700 dark:text-gray-300 text-xs">{inst.CreatedBy?.Name || '—'}</td>
                                        <td className="px-4 py-2.5 text-gray-500 dark:text-gray-400 text-xs whitespace-nowrap">{formatDate(inst.CreatedDate)}</td>
                                        <td className="px-4 py-2.5 text-gray-500 dark:text-gray-400 text-xs whitespace-nowrap">
                                            {inst.CompletedDate ? formatDate(inst.CompletedDate) : '—'}
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                ) : (
                    <div className="text-center py-12 text-gray-500 dark:text-gray-400">
                        <BarChart2 className="w-10 h-10 text-gray-300 dark:text-gray-600 mx-auto mb-2" />
                        <p className="text-sm">No approval activity recorded for this process.</p>
                        {isActive && (
                            <p className="text-xs text-gray-400 dark:text-gray-500 mt-1">
                                Submit a {getObjectLabel(process.TableEnumOrId)} record for approval to see activity here.
                            </p>
                        )}
                    </div>
                )}
            </div>

            {/* Clone Confirmation Modal */}
            <ProcessCloneModal
                isOpen={processActions.cloneModalOpen}
                cloneName={processActions.cloneName}
                setCloneName={processActions.setCloneName}
                cloneDeveloperName={processActions.cloneDeveloperName}
                setCloneDeveloperName={processActions.setCloneDeveloperName}
                cloning={processActions.cloning}
                onClone={processActions.handleCloneProcess}
                onClose={() => processActions.setCloneModalOpen(false)}
            />

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

// ============================================================================
// Sub-components
// ============================================================================

function StatCard({ label, value, icon, color }: {
    label: string;
    value: number;
    icon: React.ReactNode;
    color: 'amber' | 'green' | 'red' | 'blue';
}) {
    const colorMap = {
        amber: 'bg-amber-50 text-amber-700 border-amber-100 dark:bg-amber-900/20 dark:text-amber-400 dark:border-amber-800',
        green: 'bg-green-50 text-green-700 border-green-100 dark:bg-green-900/20 dark:text-green-400 dark:border-green-800',
        red: 'bg-red-50 text-red-700 border-red-100 dark:bg-red-900/20 dark:text-red-400 dark:border-red-800',
        blue: 'bg-blue-50 text-blue-700 border-blue-100 dark:bg-blue-900/20 dark:text-blue-400 dark:border-blue-800',
    };

    return (
        <div className={`rounded-xl border p-4 ${colorMap[color]}`}>
            <div className="flex items-center gap-2 mb-1">
                {icon}
                <span className="text-xs font-medium uppercase tracking-wider">{label}</span>
            </div>
            <p className="text-2xl font-bold">{value}</p>
        </div>
    );
}

function StatusBadge({ status }: { status: string }) {
    const config: Record<string, { bg: string; text: string; icon: React.ReactNode }> = {
        Pending: {
            bg: 'bg-amber-50 border-amber-100 dark:bg-amber-900/20 dark:border-amber-800',
            text: 'text-amber-700 dark:text-amber-400',
            icon: <Clock className="w-3 h-3" />,
        },
        Approved: {
            bg: 'bg-green-50 border-green-100 dark:bg-green-900/20 dark:border-green-800',
            text: 'text-green-700 dark:text-green-400',
            icon: <CheckCircle className="w-3 h-3" />,
        },
        Rejected: {
            bg: 'bg-red-50 border-red-100 dark:bg-red-900/20 dark:border-red-800',
            text: 'text-red-700 dark:text-red-400',
            icon: <XCircle className="w-3 h-3" />,
        },
        Removed: {
            bg: 'bg-gray-100 border-gray-200 dark:bg-gray-700 dark:border-gray-600',
            text: 'text-gray-600 dark:text-gray-400',
            icon: <XCircle className="w-3 h-3" />,
        },
    };

    const c = config[status] || config.Pending;

    return (
        <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border ${c.bg} ${c.text}`}>
            {c.icon}
            {status}
        </span>
    );
}

export default ApprovalProcessDetailPage;
