import {
  CheckOutlined,
  ClockCircleOutlined,
  CloseOutlined,
  LoadingOutlined,
} from '@ant-design/icons';
import type { CSSProperties, ReactNode } from 'react';
import type {
  ProcessFlowDirection,
  ProcessFlowStatusAppearance,
  ProcessFlowStep,
  ProcessFlowStepStatus,
  ProcessFlowUIProps,
} from './types';
import './ProcessFlowUI.css';

const defaultStatusLabels: Record<ProcessFlowStepStatus, string> = {
  complete: '완료',
  current: '진행중',
  failed: '실패',
  pending: '대기',
};

const defaultStatusIcons: Record<ProcessFlowStepStatus, ReactNode> = {
  complete: <CheckOutlined />,
  current: <LoadingOutlined />,
  failed: <CloseOutlined />,
  pending: <ClockCircleOutlined />,
};

const defaultStatusAppearance: Record<ProcessFlowStepStatus, ProcessFlowStatusAppearance> = {
  complete: {
    accent: '#16a34a',
    accentSoft: 'rgba(22, 163, 74, 0.14)',
    border: 'rgba(34, 197, 94, 0.22)',
    background: 'linear-gradient(180deg, rgba(240, 253, 244, 0.98) 0%, rgba(220, 252, 231, 0.78) 100%)',
    text: '#14532d',
    connector: 'rgba(34, 197, 94, 0.32)',
    shadow: '0 10px 24px rgba(34, 197, 94, 0.08)',
  },
  current: {
    accent: '#165dff',
    accentSoft: 'rgba(22, 93, 255, 0.12)',
    border: 'rgba(22, 93, 255, 0.24)',
    background: 'linear-gradient(180deg, rgba(239, 246, 255, 0.98) 0%, rgba(219, 234, 254, 0.84) 100%)',
    text: '#102a56',
    connector: 'rgba(22, 93, 255, 0.28)',
    shadow: '0 12px 28px rgba(22, 93, 255, 0.12)',
  },
  failed: {
    accent: '#dc2626',
    accentSoft: 'rgba(220, 38, 38, 0.12)',
    border: 'rgba(239, 68, 68, 0.24)',
    background: 'linear-gradient(180deg, rgba(254, 242, 242, 0.98) 0%, rgba(254, 226, 226, 0.84) 100%)',
    text: '#7f1d1d',
    connector: 'rgba(239, 68, 68, 0.28)',
    shadow: '0 10px 24px rgba(220, 38, 38, 0.1)',
  },
  pending: {
    accent: '#64748b',
    accentSoft: 'rgba(100, 116, 139, 0.12)',
    border: 'rgba(148, 163, 184, 0.24)',
    background: 'linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(248, 250, 252, 0.96) 100%)',
    text: '#334155',
    connector: 'rgba(148, 163, 184, 0.32)',
    shadow: 'none',
  },
};

function joinClassNames(...classNames: Array<string | false | null | undefined>) {
  return classNames.filter(Boolean).join(' ');
}

function resolveStepStatus(
  step: ProcessFlowStep,
  index: number,
  currentIndex: number,
): ProcessFlowStepStatus {
  if (step.status) {
    return step.status;
  }

  if (currentIndex < 0) {
    return 'pending';
  }

  if (index < currentIndex) {
    return 'complete';
  }

  if (index === currentIndex) {
    return 'current';
  }

  return 'pending';
}

function resolveAppearance(
  status: ProcessFlowStepStatus,
  statusStyles?: ProcessFlowUIProps['statusStyles'],
): ProcessFlowStatusAppearance {
  return {
    ...defaultStatusAppearance[status],
    ...(statusStyles?.[status] ?? {}),
  };
}

function resolveStatusLabel(
  status: ProcessFlowStepStatus,
  statusLabels?: ProcessFlowUIProps['statusLabels'],
) {
  return statusLabels?.[status] ?? defaultStatusLabels[status];
}

function buildStepStyle(appearance: ProcessFlowStatusAppearance): CSSProperties {
  return {
    '--process-flow-accent': appearance.accent,
    '--process-flow-accent-soft': appearance.accentSoft,
    '--process-flow-border': appearance.border,
    '--process-flow-background': appearance.background,
    '--process-flow-text': appearance.text,
    '--process-flow-connector': appearance.connector,
    '--process-flow-shadow': appearance.shadow ?? 'none',
  } as CSSProperties;
}

type StepNodeProps = {
  step: ProcessFlowStep;
  index: number;
  compact: boolean;
  appearance: ProcessFlowStatusAppearance;
  status: ProcessFlowStepStatus;
  statusLabel: string;
  icon: ReactNode;
  onStepClick?: ProcessFlowUIProps['onStepClick'];
};

function StepNode({
  step,
  index,
  compact,
  appearance,
  status,
  statusLabel,
  icon,
  onStepClick,
}: StepNodeProps) {
  const className = joinClassNames(
    'process-flow__step',
    compact && 'process-flow__step--compact',
    onStepClick && 'process-flow__step--button',
    status === 'current' && 'process-flow__step--current',
  );
  const style = buildStepStyle(appearance);

  if (onStepClick) {
    return (
      <button
        type="button"
        className={className}
        style={style}
        onClick={() => onStepClick(step, index)}
        aria-current={status === 'current' ? 'step' : undefined}
      >
        <span className="process-flow__marker" aria-hidden="true">
          {icon}
        </span>
        <span className="process-flow__content">
          <span className="process-flow__label-row">
            <span className="process-flow__label">{step.label}</span>
            <span className="process-flow__status">{statusLabel}</span>
          </span>
          {step.description ? (
            <span className="process-flow__description">{step.description}</span>
          ) : null}
        </span>
      </button>
    );
  }

  return (
    <div className={className} style={style} aria-current={status === 'current' ? 'step' : undefined}>
      <span className="process-flow__marker" aria-hidden="true">
        {icon}
      </span>
      <span className="process-flow__content">
        <span className="process-flow__label-row">
          <span className="process-flow__label">{step.label}</span>
          <span className="process-flow__status">{statusLabel}</span>
        </span>
        {step.description ? (
          <span className="process-flow__description">{step.description}</span>
        ) : null}
      </span>
    </div>
  );
}

export function ProcessFlowUI({
  steps,
  currentStepKey,
  direction = 'horizontal',
  compact = false,
  showConnector = true,
  onStepClick,
  statusIcons,
  statusStyles,
  statusLabels,
  className,
  style,
}: ProcessFlowUIProps) {
  const currentIndex = currentStepKey ? steps.findIndex((step) => step.key === currentStepKey) : -1;

  return (
    <div
      className={joinClassNames(
        'process-flow',
        direction === 'vertical' ? 'process-flow--vertical' : 'process-flow--horizontal',
        className,
      )}
      style={style}
      role="list"
      aria-label={`process-flow-${direction as ProcessFlowDirection}`}
    >
      {steps.map((step, index) => {
        const status = resolveStepStatus(step, index, currentIndex);
        const appearance = resolveAppearance(status, statusStyles);
        const isLast = index === steps.length - 1;
        const icon = statusIcons?.[status] ?? defaultStatusIcons[status];
        const statusLabel = resolveStatusLabel(status, statusLabels);

        return (
          <div
            key={step.key}
            className="process-flow__item"
            style={buildStepStyle(appearance)}
            role="listitem"
          >
            <StepNode
              step={step}
              index={index}
              compact={compact}
              appearance={appearance}
              status={status}
              statusLabel={statusLabel}
              icon={icon}
              onStepClick={onStepClick}
            />
            {showConnector && !isLast ? (
              <span className="process-flow__connector" aria-hidden="true" />
            ) : null}
          </div>
        );
      })}
    </div>
  );
}
