import type { PartialElement } from '@furystack/shades'
import { Shade, createComponent } from '@furystack/shades'
import { cssVariableTheme } from '../services/css-variable-theme.js'
import { paletteMainColors } from '../services/palette-css-vars.js'
import { Icon } from './icons/icon.js'
import { Typography } from './typography.js'
import {
  checkCircle,
  errorCircle,
  forbidden,
  info as infoIcon,
  searchOff,
  serverError,
  warning as warningIcon,
} from './icons/icon-definitions.js'

/**
 * Result status types. Includes both semantic statuses and HTTP error codes.
 */
export type ResultStatus = 'success' | 'error' | 'warning' | 'info' | '403' | '404' | '500'

export type ResultProps = PartialElement<HTMLElement> & {
  /** The status determines the icon and color of the result */
  status: ResultStatus
  /** The main title text */
  title: string
  /** Optional subtitle text below the title */
  subtitle?: string
  /** Optional custom icon to override the default status icon */
  icon?: JSX.Element | string
}

const statusColorMap: Record<ResultStatus, string> = {
  success: paletteMainColors.success.main,
  error: paletteMainColors.error.main,
  warning: paletteMainColors.warning.main,
  info: paletteMainColors.info.main,
  '403': paletteMainColors.warning.main,
  '404': paletteMainColors.info.main,
  '500': paletteMainColors.error.main,
}

const defaultIconDefs: Record<ResultStatus, typeof checkCircle> = {
  success: checkCircle,
  error: errorCircle,
  warning: warningIcon,
  info: infoIcon,
  '403': forbidden,
  '404': searchOff,
  '500': serverError,
}

const getDefaultIcon = (status: ResultStatus): JSX.Element => <Icon icon={defaultIconDefs[status]} size={64} />

const defaultTitles: Record<ResultStatus, string> = {
  success: 'Success',
  error: 'Error',
  warning: 'Warning',
  info: 'Information',
  '403': '403 - Forbidden',
  '404': '404 - Not Found',
  '500': '500 - Internal Server Error',
}

/**
 * Result component for displaying operation outcomes, status pages, and feedback.
 * Supports success, error, warning, info statuses and common HTTP error codes (403, 404, 500).
 */
export const Result = Shade<ResultProps>({
  customElementName: 'shade-result',
  css: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    textAlign: 'center',
    padding: `${cssVariableTheme.spacing.xl} ${cssVariableTheme.spacing.lg}`,
    fontFamily: cssVariableTheme.typography.fontFamily,
    boxSizing: 'border-box',

    // ==========================================
    // ICON
    // ==========================================

    '& .result-icon': {
      fontSize: '64px',
      lineHeight: '1',
      marginBottom: cssVariableTheme.spacing.lg,
      color: 'var(--result-status-color)',
    },

    // ==========================================
    // TITLE
    // ==========================================

    '& .result-title': {
      marginBottom: cssVariableTheme.spacing.sm,
    },

    '& .result-subtitle': {
      marginBottom: cssVariableTheme.spacing.lg,
      maxWidth: '480px',
    },

    // ==========================================
    // EXTRA (actions area)
    // ==========================================

    '& .result-extra': {
      display: 'flex',
      gap: cssVariableTheme.spacing.md,
      marginTop: cssVariableTheme.spacing.md,
      flexWrap: 'wrap',
      justifyContent: 'center',
    },
  },
  render: ({ props, children, useHostProps }) => {
    const { status, title, subtitle, icon, style } = props

    const displayIcon = icon ?? getDefaultIcon(status)
    const statusColor = statusColorMap[status]

    useHostProps({
      'data-status': status,
      style: {
        '--result-status-color': statusColor,
        ...(style as Record<string, string>),
      },
    })

    const hasChildren = children && (Array.isArray(children) ? children.length > 0 : true)

    return (
      <>
        <span className="result-icon" role="img">
          {displayIcon}
        </span>
        <Typography variant="h5" className="result-title" style={{ margin: '0' }}>
          {title}
        </Typography>
        {subtitle ? (
          <Typography variant="body2" color="textSecondary" className="result-subtitle" style={{ margin: '0' }}>
            {subtitle}
          </Typography>
        ) : null}
        {hasChildren ? <div className="result-extra">{children}</div> : null}
      </>
    )
  },
})

export {
  getDefaultIcon as resultGetDefaultIcon,
  defaultIconDefs as resultDefaultIconDefs,
  defaultTitles as resultDefaultTitles,
}
