import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Button, Container, Heading, Input, Text, toast } from "@medusajs/ui"
import { useEffect, useState } from "react"
import type { AdminProduct, DetailWidgetProps } from "@medusajs/framework/types"
import { sdk } from "../lib/sdk"
import { useTranslation } from "react-i18next"
import { normalizeValue, isContentEqual, deepClone } from "../lib/cms-utils"

type CompositionRow = {
  label: string
  value_label: string
  percentage: string
}

const EMPTY_ROW: CompositionRow = {
  label: "",
  value_label: "",
  percentage: "",
}

const TypicalCompositionWidget = ({
  data: product,
}: DetailWidgetProps<AdminProduct>) => {
  const { t } = useTranslation()
  const [rows, setRows] = useState<CompositionRow[]>([])
  const [lastSaved, setLastSaved] = useState<CompositionRow[] | null>(null)
  const [isSaving, setIsSaving] = useState(false)

  useEffect(() => {
    const existingComposition = product?.metadata?.typical_composition

    if (!Array.isArray(existingComposition)) {
      setRows([])
      return
    }

    const nextRows = existingComposition
      .map((item) => {
        if (!item || typeof item !== "object") {
          return null
        }

        const record = item as Record<string, unknown>
        return {
          label: typeof record.label === "string" ? record.label : "",
          value_label:
            typeof record.value_label === "string"
              ? record.value_label
              : typeof record.value === "string"
                ? record.value
                : "",
          percentage:
            typeof record.percentage === "number" && Number.isFinite(record.percentage)
              ? String(record.percentage)
              : "",
        }
      })
      .filter((item): item is CompositionRow => Boolean(item))

    setRows(nextRows)
    setLastSaved(normalizeValue(nextRows))
  }, [product])

  const handleAddRow = () => {
    setRows((current) => [...current, { ...EMPTY_ROW }])
  }

  const handleRemoveRow = (index: number) => {
    setRows((current) => current.filter((_, currentIndex) => currentIndex !== index))
  }

  const handleChange = (
    index: number,
    field: keyof CompositionRow,
    value: string
  ) => {
    setRows((current) =>
      current.map((row, currentIndex) =>
        currentIndex === index ? { ...row, [field]: value } : row
      )
    )
  }

  const handleSave = async () => {
    if (!product?.id) {
      toast.error(t("biomketProduct.typicalComposition.productMissing"))
      return
    }

    setIsSaving(true)

    const typicalComposition = rows
      .map((row) => ({
        label: row.label.trim(),
        value_label: row.value_label.trim(),
        percentage: Number(row.percentage),
      }))
      .filter(
        (row) =>
          row.label &&
          row.value_label &&
          Number.isFinite(row.percentage) &&
          row.percentage >= 0 &&
          row.percentage <= 100
      )

    const updatedMetadata = {
      ...(product.metadata || {}),
      typical_composition: typicalComposition,
    }

    try {
      const response = await sdk.fetch(`/admin/products/${product.id}`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          metadata: updatedMetadata,
        }),
      })

      if (response.ok) {
        toast.success(t("biomketProduct.typicalComposition.saveSuccess"))
        setLastSaved(normalizeValue(rows))
        return
      }

      const message = await response.text()
      throw new Error(message || t("biomketProduct.typicalComposition.saveError"))
    } catch (error) {
      console.error(error)
      toast.error(
        error instanceof Error
          ? error.message
          : t("biomketProduct.typicalComposition.saveError")
      )
    } finally {
      setIsSaving(false)
    }
  }

  return (
    <Container className="p-4">
      <div className="mb-6 flex items-center justify-between">
        <Heading level="h2">{t("biomketProduct.typicalComposition.title")}</Heading>
        <Button variant="secondary" size="small" onClick={handleAddRow}>
          {t("biomketProduct.typicalComposition.addRow")}
        </Button>
      </div>

      <div className="flex flex-col gap-4">
        {rows.length === 0 ? (
          <Text className="text-gray-500">{t("biomketProduct.typicalComposition.empty")}</Text>
        ) : (
          rows.map((row, index) => (
            <div key={index} className="grid grid-cols-[1.4fr_1fr_120px_auto] gap-4">
              <Input
                placeholder={t("biomketProduct.typicalComposition.labelPlaceholder")}
                value={row.label}
                onChange={(e) => handleChange(index, "label", e.target.value)}
              />
              <Input
                placeholder={t("biomketProduct.typicalComposition.valuePlaceholder")}
                value={row.value_label}
                onChange={(e) => handleChange(index, "value_label", e.target.value)}
              />
              <Input
                type="number"
                min={0}
                max={100}
                placeholder={t("biomketProduct.typicalComposition.percentPlaceholder")}
                value={row.percentage}
                onChange={(e) => handleChange(index, "percentage", e.target.value)}
              />
              <Button
                variant="danger"
                size="small"
                onClick={() => handleRemoveRow(index)}
              >
                {t("biomketProduct.common.delete")}
              </Button>
            </div>
          ))
        )}
      </div>

      <div className="mt-6 flex justify-end">
        <Button 
          variant="primary" 
          onClick={handleSave} 
          isLoading={isSaving}
          disabled={lastSaved !== null && isContentEqual(rows, lastSaved)}
        >
          {t("biomketProduct.typicalComposition.save")}
        </Button>
      </div>
    </Container>
  )
}

export const config = defineWidgetConfig({
  zone: "product.details.after",
})

export default TypicalCompositionWidget
