import { ActionAddNode, ArrowNode, ConnectionLine, ModelNode, NodeContainer, ProviderNode, SmartOpNode } from '@/components/nodes';
import {
    Add as AddIcon,
    ExpandMore as ExpandMoreIcon,
    Warning as WarningIcon,
} from '@mui/icons-material';
import {
    Box,
    Button,
    Card,
    CardContent,
    Chip,
    Collapse,
    IconButton,
    Stack,
    Tooltip,
    Typography,
} from '@mui/material';
import { styled } from '@mui/material/styles';
import React from 'react';
import { notify } from '@/utils/notify';
import type { Provider } from '../types/provider';
import type { ConfigRecord } from './RoutingGraphTypes.ts';

// Unified RuleGraph style configuration
const RULE_GRAPH_STYLES = {
    // Node dimensions
    node: {
        width: 320,
        height: 120,
        heightCompact: 60,
        padding: 10,  // Container padding
    },
    // Spacing
    spacing: {
        xs: 4,   // 0.5
        sm: 8,   // 1
        md: 12,  // 1.5
        lg: 16,  // 2
        xl: 16,  // 3
    },
    // Header
    header: {
        paddingX: 16,  // spacing(2)
        paddingY: 6,   // spacing(0.75) - reduced from 8 for smaller height
    },
    // Graph container
    graphContainer: {
        paddingX: 16,  // spacing(2)
        paddingY: 8,  // Reduced from 12
        marginX: 16,   // spacing(2)
        marginY: 6,    // spacing(1)
    },
    // Graph content spacing
    graph: {
        stackSpacing: 0,      // Stack spacing between sections
        modelGap: 8,          // Gap between model nodes
        labelMargin: 2,       // Margin below labels
        rowGap: 16,           // Gap between graph rows
        iconGap: 2,           // Gap between icon and text
        wrapperGap: 8,        // Gap in wrapper boxes
    },
    // Model node specific
    modelNode: {
        padding: 10,          // Internal padding - same as node.padding
    },
    // Provider node internal
    providerNode: {
        badgeHeight: 5,       // API Style badge
        fieldHeight: 5,       // Provider/Model fields
        fieldPadding: 2,      // Internal padding
        elementMargin: 1,     // Margin between elements
    },
} as const;

// Shorthand for common values
const { node, header, graphContainer, graph } = RULE_GRAPH_STYLES;

interface RuleGraphProps {
    record: ConfigRecord;
    providers: any[];
    saving: boolean;
    expanded: boolean;
    collapsible?: boolean;
    allowToggleRule?: boolean;
    recordUuid: string;
    onUpdateRecord: (field: keyof ConfigRecord, value: any) => void;
    onDeleteProvider: (recordId: string, providerId: string) => void;
    onProviderPriorityChange?: (providerUuid: string, priority: number) => void;
    onToggleExpanded: () => void;
    onProviderNodeClick: (providerUuid: string) => void;
    onAddProviderButtonClick: () => void;
    extraActions?: React.ReactNode;
    // Slot rendered at the right end of the rule group (e.g. rule extensions card)
    extensionsCard?: React.ReactNode;
    // Smart routing props
    onAddSmartRule?: () => void;
    onEditSmartRule?: (ruleUuid: string) => void;
    onDeleteSmartRule?: (ruleUuid: string) => void;
    onAddServiceToSmartRule?: (ruleUuid: string) => void;
    onDeleteServiceFromSmartRule?: (ruleUuid: string, serviceUuid: string) => void;
    // Routing mode switch
    onSwitchRoutingMode?: () => void;
}

const StyledCard = styled(Card, {
    shouldForwardProp: (prop) => prop !== 'active',
})<{ active: boolean }>(({ active, theme }) => ({
    transition: 'all 0.2s ease-in-out',
    opacity: active ? 1 : 0.6,
    filter: active ? 'none' : 'grayscale(0.3)',
    border: active ? 'none' : '2px dashed',
    borderColor: active ? 'transparent' : theme.palette.text.disabled,
    margin: "3px",
    position: 'relative',
    ...(active ? {} : {
        '&::before': {
            content: '""',
            position: 'absolute',
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
            backgroundImage: 'repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(0,0,0,0.03) 10px, rgba(0,0,0,0.03) 20px)',
            pointerEvents: 'none',
            borderRadius: theme.shape.borderRadius,
        },
    }),
    '&:hover': {
        boxShadow: active ? theme.shadows[4] : theme.shadows[1],
    },
}));

const SummarySection = styled(Box, {
    shouldForwardProp: (prop) => prop !== 'collapsible',
})<{ collapsible?: boolean }>(({ collapsible }) => ({
    display: 'flex',
    flexWrap: 'wrap',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: `${header.paddingY}px ${header.paddingX}px`,
    cursor: collapsible ? 'pointer' : 'default',
    ...(collapsible && {
        '&:hover': {
            backgroundColor: 'action.hover',
        },
    }),
}));

// Graph Container for expanded view
const GraphContainer = styled(Box)(({ theme }) => ({
    padding: `${graphContainer.paddingY}px ${graphContainer.paddingX}px`,
    backgroundColor: 'grey.50',
    borderRadius: theme.shape.borderRadius,
    margin: `${graphContainer.marginY}px ${graphContainer.marginX}px 0`,
}));

const GraphRow = styled(Box)(({ theme }) => ({
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-start',
    gap: graph.rowGap,
    marginBottom: theme.spacing(0.5),
}));

// Main RuleGraph Component
const RoutingGraph: React.FC<RuleGraphProps> = ({
    record,
    providers,
    saving,
    expanded,
    collapsible = false,
    recordUuid,
    onUpdateRecord,
    onDeleteProvider,
    onProviderPriorityChange,
    onToggleExpanded,
    onProviderNodeClick,
    onAddProviderButtonClick,
    extraActions,
    extensionsCard,
    // Smart routing props
    onAddSmartRule,
    onEditSmartRule,
    onDeleteSmartRule,
    onAddServiceToSmartRule,
    onDeleteServiceFromSmartRule,
    // Routing mode switch
    onSwitchRoutingMode,
}) => {
    // When users explicitly set priorities on services we render the
    // default-providers list sorted by Priority (descending — higher
    // first) so the visual sequence matches the runtime fallback
    // sequence. Without explicit priorities we preserve the array order
    // from the rule.
    const sortedDefaultProviders = React.useMemo(() => {
        const list = record.providers;
        const hasAnyPriority = list.some((p) => (p.priority ?? 0) > 0);
        if (!hasAnyPriority) return list;
        return [...list].sort((a, b) => {
            const ap = a.priority ?? 0;
            const bp = b.priority ?? 0;
            // 0 sinks to the bottom so explicitly-prioritised services appear first.
            if (ap === 0 && bp !== 0) return 1;
            if (bp === 0 && ap !== 0) return -1;
            return bp - ap;
        });
    }, [record.providers]);
    // When collapsible, parent controls expanded state (defaults to false when collapsible=true)
    // When not collapsible, always show expanded
    const isExpanded = !collapsible || expanded;
    const getApiStyle = (providerUuid: string) => {
        const provider = providers.find(p => p.uuid === providerUuid);
        return provider?.api_style || 'openai';
    };

    const showNotification = (message: string) => {
        notify.success(message);
    };

    const handleCopyModel = (e: React.MouseEvent) => {
        e.stopPropagation();
        if (record.requestModel) {
            void navigator.clipboard.writeText(record.requestModel);
            showNotification(`Model name "${record.requestModel}" copied to clipboard`);
        }
    };

    const smartEnabled = record.smartEnabled || false;
    const smartRouting = record.smartRouting || [];
    const hasSmartRules = smartRouting.length > 0;

    return (
        <StyledCard active={record.active}>
            {/* Header Section - RuleCard Style */}
            <SummarySection
                collapsible={collapsible}
                onClick={collapsible ? onToggleExpanded : undefined}
            >
                {/* Left side */}
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, flexGrow: 1, minWidth: 0 }}>
                    <Tooltip title={record.requestModel
                        ? `Use "${record.requestModel}" as model name in your API requests. (click to copy)`
                        : 'No model specified'}>
                        <Typography
                            onClick={handleCopyModel}
                            sx={{
                                fontFamily: 'monospace',
                                fontSize: '0.875rem',
                                fontWeight: 600,
                                color: record.active ? 'text.primary' : 'text.disabled',
                                opacity: record.active ? 1 : 0.5,
                                cursor: record.requestModel ? 'pointer' : 'default',
                                '&:hover': record.requestModel ? {
                                    color: 'primary.dark',
                                } : {},
                            }}
                        >
                            model = {record.requestModel || 'Unspecified'}
                        </Typography>
                    </Tooltip>
                    {/* Rule Description - moved to top bar with auto-truncate, after active badge */}
                    {record.description && (
                        <Tooltip title={record.description} arrow>
                            <Typography
                                variant="caption"
                                sx={{
                                    color: 'text.secondary',
                                    fontSize: '0.75rem',
                                    fontStyle: 'italic',
                                    overflow: 'hidden',
                                    textOverflow: 'ellipsis',
                                    whiteSpace: 'nowrap',
                                    maxWidth: '400px',
                                }}
                            >
                                {record.description}
                            </Typography>
                        </Tooltip>
                    )}
                    {record.active && record.providers.length === 0 && (
                        <Tooltip title="No providers configured - add a provider to enable request forwarding">
                            <WarningIcon
                                sx={{
                                    fontSize: '1.1rem',
                                    color: 'warning.main',
                                    animation: 'pulse 2s ease-in-out infinite',
                                    '@keyframes pulse': {
                                        '0%, 100%': { opacity: 1 },
                                        '50%': { opacity: 0.5 },
                                    },
                                }}
                            />
                        </Tooltip>
                    )}
                </Box>
                {/* Right side */}
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
                    <Box onClick={(e) => e.stopPropagation()}>{extraActions}</Box>
                    {record.responseModel && <Chip
                        label={`Response as ${record.responseModel}`}
                        size="small"
                        color="info"
                        onClick={(e) => e.stopPropagation()}
                        sx={{
                            opacity: record.active ? 1 : 0.5,
                            backgroundColor: record.active ? 'info.main' : 'action.disabled',
                            color: record.active ? 'info.contrastText' : 'text.disabled'
                        }}
                    />}
                    {collapsible && (
                        <IconButton
                            size="small"
                            onClick={(e) => {
                                e.stopPropagation();
                                onToggleExpanded();
                            }}
                            sx={{
                                transition: 'transform 0.2s',
                                transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
                            }}
                        >
                            <ExpandMoreIcon />
                        </IconButton>
                    )}
                </Box>
            </SummarySection>

            {/* Expanded Content - Graph View */}
            <Collapse in={isExpanded} timeout="auto" unmountOnExit>
                <CardContent sx={{ pt: 0, pb: 0.25, '&:last-child': { pb: 0.25 } }}>
                    <Stack spacing={graph.stackSpacing}>
                        {/* Graph row: scrollable graph + pinned extensions card */}
                        <Box sx={{ display: 'flex', alignItems: 'stretch', minWidth: 0 }}>
                            <Box sx={{ flexGrow: 1, minWidth: 0, overflowX: 'auto' }}>
                                <GraphContainer>
                                    <GraphRow>
                                        {/* Request Model section */}
                                        <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', pr: 1, }}>
                                        <NodeContainer>
                                            {record.responseModel ? (
                                                // Split display when response model is configured
                                                <Box sx={{ display: 'flex', flexDirection: 'column', gap: graph.modelGap }}>
                                                    {/* Request Model Card */}
                                                    <Box sx={{ display: 'flex', alignItems: 'center', gap: graph.wrapperGap }}>
                                                        <Box sx={{ flex: 1 }}>
                                                            <Tooltip title="The model name that clients use to make requests. This will be matched against incoming API calls." placement="top" arrow>
                                                                <Box>
                                                                    <ModelNode
                                                                        active={record.active}
                                                                        label="Unspecified"
                                                                        value={record.requestModel}
                                                                        editable={record.active}
                                                                        onUpdate={(value) => onUpdateRecord('requestModel', value)}
                                                                        compact={true}
                                                                        showSmartSwitch={true}
                                                                        smartEnabled={smartEnabled}
                                                                        switchDisabled={saving}
                                                                        onSwitch={() => onSwitchRoutingMode?.()}
                                                                    />
                                                                </Box>
                                                            </Tooltip>
                                                        </Box>
                                                    </Box>

                                                    {/* Response Model Card */}
                                                    <Box sx={{ display: 'flex', alignItems: 'center', gap: graph.wrapperGap }}>
                                                        <Box sx={{ flex: 1 }}>
                                                            <Tooltip title="The model name returned to clients. Responses from upstream providers will be transformed to show this model name instead." placement="top" arrow>
                                                                <Box>
                                                                    <ModelNode
                                                                        active={record.active}
                                                                        label=""
                                                                        value={record.responseModel}
                                                                        editable={true}
                                                                        onUpdate={(value) => onUpdateRecord('responseModel', value)}
                                                                        compact={true}
                                                                    />
                                                                </Box>
                                                            </Tooltip>
                                                        </Box>
                                                    </Box>
                                                </Box>
                                            ) : (
                                                // Single display when no response model
                                                <Tooltip title="The model name that clients use to make requests. This will be matched against incoming API calls." placement="top" arrow>
                                                    <Box>
                                                        <ModelNode
                                                            active={record.active}
                                                            label="Unspecified"
                                                            value={record.requestModel}
                                                            editable={record.active}
                                                            onUpdate={(value) => onUpdateRecord('requestModel', value)}
                                                            showSmartSwitch={true}
                                                            smartEnabled={smartEnabled}
                                                            switchDisabled={saving}
                                                            onSwitch={() => onSwitchRoutingMode?.()}
                                                        />
                                                    </Box>
                                                </Tooltip>
                                            )}
                                        </NodeContainer>
                                    </Box>

                                    {/* Arrow to providers - aligned to center of ModelNode */}
                                    <Box sx={{ flex: 0, display: 'flex', alignItems: 'center' }}>
                                        <ArrowNode direction={record.responseModel ? 'bidirectional' : 'forward'} flowing={false} flowSpeed={1.} />
                                    </Box>

                                    {/* Smart Rules Section - Vertical layout between model and providers */}
                                    {smartEnabled && hasSmartRules ? (
                                        // Smart routing layout: Model → Smart Rules (vertical) → Default Providers
                                        <>
                                            {/* Arrow from model to first smart rule */}
                                            <ArrowNode direction="down" flowing={false} flowSpeed={1.} />

                                            {/* Smart Rules Stack - Each rule is a row with SmartOpNode and its services */}
                                            <Box sx={{ display: 'flex', flexDirection: 'column', gap: graph.rowGap }}>
                                                {smartRouting.map((rule) => (
                                                    <GraphRow key={rule.uuid} sx={{ mb: 0 }}>
                                                        {/* Smart Node */}
                                                        <NodeContainer>
                                                            <SmartOpNode
                                                                smartRouting={rule}
                                                                active={record.active}
                                                                onEdit={() => onEditSmartRule?.(rule.uuid)}
                                                                onDelete={() => onDeleteSmartRule?.(rule.uuid)}
                                                            />
                                                        </NodeContainer>

                                                        {/* Arrow to services */}
                                                        <ArrowNode direction="forward" flowing={false} flowSpeed={1.} />

                                                        {/* Services for this smart rule */}
                                                        {rule.services && rule.services.length > 0 ? (
                                                            <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                                                                <Typography variant="caption" sx={{ color: 'text.secondary', mb: graph.labelMargin }}>
                                                                    Services
                                                                </Typography>
                                                                <Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'nowrap', justifyContent: 'flex-start', alignItems: 'center' }}>
                                                                    {rule.services.map((service) => (
                                                                        <ProviderNode
                                                                            key={service.uuid}
                                                                            provider={service}
                                                                            apiStyle={getApiStyle(service.provider)}
                                                                            providersData={providers as Provider[]}
                                                                            active={record.active && service.active !== false}
                                                                            onDelete={() => onDeleteServiceFromSmartRule?.(rule.uuid, service.uuid)}
                                                                            onNodeClick={() => onProviderNodeClick(service.uuid)}
                                                                        />
                                                                    ))}
                                                                    <Tooltip title="Add service to this smart rule">
                                                                        <IconButton
                                                                            onClick={(e) => {
                                                                                e.stopPropagation();
                                                                                onAddServiceToSmartRule?.(rule.uuid);
                                                                            }}
                                                                            disabled={!record.active || saving}
                                                                            sx={{
                                                                                width: node.width,
                                                                                height: node.height,
                                                                                border: '2px dashed',
                                                                                borderColor: 'divider',
                                                                                borderRadius: 2,
                                                                                backgroundColor: 'background.paper',
                                                                                boxShadow: theme => theme.shadows[2],
                                                                                transition: 'all 0.2s ease-in-out',
                                                                                display: 'flex',
                                                                                flexDirection: 'column',
                                                                                justifyContent: 'center',
                                                                                alignItems: 'center',
                                                                                gap: 1,
                                                                                '&:hover': {
                                                                                    borderColor: 'primary.main',
                                                                                    backgroundColor: 'action.hover',
                                                                                    borderStyle: 'solid',
                                                                                    boxShadow: theme => theme.shadows[4],
                                                                                    transform: 'translateY(-2px)',
                                                                                },
                                                                                '&:disabled': {
                                                                                    borderColor: 'action.disabled',
                                                                                    backgroundColor: 'action.disabledBackground',
                                                                                }
                                                                            }}
                                                                        >
                                                                            <AddIcon sx={{ fontSize: 40, color: 'text.secondary' }} />
                                                                            <Typography variant="body2" color="text.secondary" textAlign="center">
                                                                                Add Service
                                                                            </Typography>
                                                                        </IconButton>
                                                                    </Tooltip>
                                                                </Box>
                                                            </Box>
                                                        ) : (
                                                            <Box sx={{ textAlign: 'left', py: 2 }}>
                                                                <Typography variant="body2" color="text.secondary" gutterBottom>
                                                                    No services for this rule
                                                                </Typography>
                                                                <Tooltip title="Add first service to this smart rule">
                                                                    <IconButton
                                                                        onClick={(e) => {
                                                                            e.stopPropagation();
                                                                            onAddServiceToSmartRule?.(rule.uuid);
                                                                        }}
                                                                        disabled={!record.active || saving}
                                                                        sx={{
                                                                            width: 48,
                                                                            height: 48,
                                                                            border: '2px dashed',
                                                                            borderColor: 'divider',
                                                                            borderRadius: 2,
                                                                            backgroundColor: 'background.paper',
                                                                            '&:hover': {
                                                                                borderColor: 'primary.main',
                                                                                backgroundColor: 'action.hover',
                                                                                borderStyle: 'solid',
                                                                            },
                                                                            '&:disabled': {
                                                                                borderColor: 'action.disabled',
                                                                                backgroundColor: 'action.disabledBackground',
                                                                            }
                                                                        }}
                                                                    >
                                                                        <AddIcon sx={{ fontSize: 28, color: 'text.secondary' }} />
                                                                    </IconButton>
                                                                </Tooltip>
                                                            </Box>
                                                        )}
                                                    </GraphRow>
                                                ))}

                                                {/* Add Smart Rule Button */}
                                                <Box sx={{ display: 'flex', justifyContent: 'flex-start', py: 1 }}>
                                                    <Button
                                                        variant="outlined"
                                                        startIcon={<AddIcon />}
                                                        onClick={(e) => {
                                                            e.stopPropagation();
                                                            onAddSmartRule?.();
                                                        }}
                                                        disabled={!record.active || saving}
                                                        sx={{
                                                            borderColor: 'primary.main',
                                                            color: 'primary.main',
                                                            '&:hover': {
                                                                borderColor: 'primary.dark',
                                                                backgroundColor: 'primary.50',
                                                            },
                                                            '&:disabled': {
                                                                borderColor: 'action.disabled',
                                                                color: 'text.disabled',
                                                            }
                                                        }}
                                                    >
                                                        Add Smart Rule
                                                    </Button>
                                                </Box>
                                            </Box>

                                            {/* Arrow from smart rules to default providers */}
                                            {record.providers.length > 0 && (
                                                <ArrowNode direction="down" flowing={false} flowSpeed={1.} />
                                            )}
                                        </>
                                    ) : <></>}

                                    {/* Providers Container - Default providers for normal mode or default for smart routing */}
                                    <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                                        <Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'nowrap', justifyContent: 'flex-start', alignItems: 'center' }}>
                                            {sortedDefaultProviders.map((provider, index) => (
                                                <Tooltip
                                                    key={provider.uuid}
                                                    title={
                                                        smartEnabled && hasSmartRules
                                                            ? 'Default provider (default when no smart rules match)'
                                                            : (provider.priority ?? 0) > 0
                                                                ? `Priority ${provider.priority} (higher = tried first)`
                                                                : record.providers.length >= 2
                                                                    ? `Provider ${index + 1} of ${record.providers.length} (requests are load balanced)`
                                                                    : 'Provider for request forwarding'
                                                    }
                                                    placement="top"
                                                    arrow
                                                >
                                                    <Box>
                                                        <ProviderNode
                                                            provider={provider}
                                                            apiStyle={getApiStyle(provider.provider)}
                                                            providersData={providers as Provider[]}
                                                            active={record.active && provider.active !== false}
                                                            onDelete={() => onDeleteProvider(recordUuid, provider.uuid)}
                                                            onNodeClick={() => onProviderNodeClick(provider.uuid)}
                                                            onPriorityChange={
                                                                onProviderPriorityChange
                                                                    ? (priority) => onProviderPriorityChange(provider.uuid, priority)
                                                                    : undefined
                                                            }
                                                        />
                                                    </Box>
                                                </Tooltip>
                                            ))}
                                            <ActionAddNode
                                                active={record.active && !saving}
                                                onAdd={() => onAddProviderButtonClick()}
                                                tooltip={
                                                    record.providers.length === 0
                                                        ? "Add a provider to enable request forwarding"
                                                        : record.providers.length === 1
                                                            ? "Add another provider (with 2+ providers, load balancing will be enabled based on strategy)"
                                                            : "Add another provider (requests will be load balanced across all providers)"
                                                }
                                            />
                                        </Box>
                                    </Box>

                                    </GraphRow>
                                </GraphContainer>
                            </Box>
                            {/* Rule Extensions slot - pinned to the right of the rule group, outside horizontal scroll */}
                            {extensionsCard && (
                                <Box
                                    onClick={(e) => e.stopPropagation()}
                                    sx={{
                                        display: 'flex',
                                        alignItems: 'center',
                                        flexShrink: 0,
                                        pl: 1,
                                        pr: `${graphContainer.marginX}px`,
                                        py: `${graphContainer.marginY}px`,
                                    }}
                                >
                                    {extensionsCard}
                                </Box>
                            )}
                        </Box>
                    </Stack>
                </CardContent>
            </Collapse>
        </StyledCard>
    );
};

export default RoutingGraph;