import {
  Block,
  ButtonIcon,
  Check,
  Close,
  Input,
  LabelSmall,
  ParagraphSmall,
  Spinner,
  useStyletron,
} from "@mezo-org/mezo-clay"
import React, { useCallback, useEffect, useState } from "react"
import EditIcon from "../../../assets/EditIcon"

type InlineEditFieldProps = {
  label: string
  value: string
  placeholder?: string
  onSave: (value: string) => Promise<void>
  validate?: (value: string) => string | null
  isLoading?: boolean
}

type InlineFieldWrapperProps = {
  label: string
  children: React.ReactNode
}

function InlineFieldWrapper({ label, children }: InlineFieldWrapperProps) {
  const [, theme] = useStyletron()

  return (
    <Block
      display="flex"
      flexDirection="column"
      overrides={{
        Block: {
          style: {
            gap: theme.sizing.scale200,
          },
        },
      }}
    >
      <LabelSmall color={theme.colors.contentSecondary}>{label}</LabelSmall>
      {children}
    </Block>
  )
}

export default function InlineEditField(props: InlineEditFieldProps) {
  const { label, value, placeholder, onSave, validate, isLoading } = props

  const [, theme] = useStyletron()
  const [isEditing, setIsEditing] = useState(false)
  const [editValue, setEditValue] = useState(value)
  const [error, setError] = useState<string | null>(null)
  const [isSaving, setIsSaving] = useState(false)

  useEffect(() => {
    setEditValue(value)
  }, [value])

  const handleEdit = useCallback(() => {
    setIsEditing(true)
    setEditValue(value)
    setError(null)
  }, [value])

  const handleCancel = useCallback(() => {
    setIsEditing(false)
    setEditValue(value)
    setError(null)
  }, [value])

  const handleSave = useCallback(async () => {
    if (validate) {
      const validationError = validate(editValue)
      if (validationError) {
        setError(validationError)
        return
      }
    }

    setIsSaving(true)
    try {
      await onSave(editValue)
      setIsEditing(false)
      setError(null)
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to save")
    } finally {
      setIsSaving(false)
    }
  }, [editValue, onSave, validate])

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === "Enter") {
        handleSave()
      } else if (e.key === "Escape") {
        handleCancel()
      }
    },
    [handleSave, handleCancel],
  )

  if (isLoading) {
    return (
      <InlineFieldWrapper label={label}>
        <Block
          display="flex"
          alignItems="center"
          height={theme.sizing.scale950}
        >
          <Spinner $size={theme.sizing.scale600} />
        </Block>
      </InlineFieldWrapper>
    )
  }

  if (isEditing) {
    return (
      <InlineFieldWrapper label={label}>
        <Block
          display="flex"
          alignItems="center"
          width="100%"
          gridGap="scale300"
          height={theme.sizing.scale950}
        >
          <Block flex={1}>
            <Input
              value={editValue}
              onChange={(e) => {
                setEditValue(e.currentTarget.value)
                setError(null)
              }}
              onKeyDown={handleKeyDown}
              placeholder={placeholder}
              size="small"
              error={!!error}
              disabled={isSaving}
              autoFocus
            />
          </Block>
          <ButtonIcon
            onClick={handleSave}
            size="small"
            shape="circle"
            kind="secondary"
            disabled={isSaving}
            aria-label="Save"
          >
            {isSaving ? (
              <Spinner $size={theme.sizing.scale500} />
            ) : (
              <Check size={14} color="currentColor" />
            )}
          </ButtonIcon>
          <ButtonIcon
            onClick={handleCancel}
            size="small"
            shape="circle"
            kind="tertiary"
            disabled={isSaving}
            aria-label="Cancel"
          >
            <Close size={14} color="currentColor" />
          </ButtonIcon>
        </Block>
        {error && (
          <ParagraphSmall
            color={theme.colors.contentNegative}
            marginTop={0}
            marginBottom={0}
          >
            {error}
          </ParagraphSmall>
        )}
      </InlineFieldWrapper>
    )
  }

  return (
    <InlineFieldWrapper label={label}>
      <Block
        display="flex"
        alignItems="center"
        justifyContent="space-between"
        height={theme.sizing.scale950}
        onClick={handleEdit}
        overrides={{
          Block: {
            style: {
              cursor: "pointer",
              minHeight: theme.sizing.scale950,
            },
          },
        }}
      >
        <ParagraphSmall
          marginTop={0}
          marginBottom={0}
          color={
            value ? theme.colors.contentPrimary : theme.colors.contentTertiary
          }
        >
          {value || placeholder}
        </ParagraphSmall>
        <EditIcon size={16} color={theme.colors.contentTertiary} />
      </Block>
    </InlineFieldWrapper>
  )
}
