import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Button, Container, Input, Select, Text, toast } from "@medusajs/ui"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { useEffect, useState } from "react"
import { sdk } from "../lib/sdk"
import { useTranslation } from "react-i18next"
import { normalizeValue, isContentEqual } from "../lib/cms-utils"

// Availability options for the dropdown
const AVAILABILITY_VALUES = ["In Stock", "Out of Stock", "On Request", "Recurring Supply"] as const
type AvailabilityValue = typeof AVAILABILITY_VALUES[number] | ""

// These are "manual overrides" — if saved, skip dynamic auto-select
const MANUAL_STATUSES = ["On Request", "Recurring Supply", "Out of Stock"] as const
type ManualStatus = typeof MANUAL_STATUSES[number]
const isManualStatus = (v: string): v is ManualStatus =>
  MANUAL_STATUSES.includes(v as ManualStatus)

type SubLocationRecord = {
  id: string
  location_id: string
  name: string
}

type LocationRecord = {
  id: string
  name: string
  sub_locations: SubLocationRecord[]
}

type ProductResponse = {
  product?: {
    id: string
    metadata?: Record<string, unknown> | null
    marketplace_detail?: {
      id?: string
      availability?: string | null
      available_quantity?: string | null
      supply_frequency?: string | null
      waste_type?: string | null
      unit?: string | null
      location?: string | null
    } | null
    current_available_quantity?: number | null
    stocked_quantity?: number | null
    reserved_quantity?: number | null
  }
}

type MarketplaceFieldState = {
  availability: AvailabilityValue
  available_quantity: string
  supply_frequency: string
  waste_type: string
  unit: string
}

const findMetadataValue = (
  metadata: Record<string, unknown> | null | undefined,
  keys: string[]
) => {
  if (!metadata) {
    return ""
  }

  const matchedKey = Object.keys(metadata).find((key) =>
    keys.some((candidate) => key.toLowerCase() === candidate.toLowerCase())
  )

  if (!matchedKey) {
    return ""
  }

  const value = metadata[matchedKey]
  return typeof value === "string" ? value : ""
}

const INITIAL_FIELDS: MarketplaceFieldState = {
  availability: "",
  available_quantity: "",
  supply_frequency: "",
  waste_type: "",
  unit: "",
}

const ProductAvailabilityWidget = ({ data }: { data: { id: string } }) => {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const [fields, setFields] = useState(INITIAL_FIELDS)
  const [location, setLocation] = useState("")
  const [lastSaved, setLastSaved] = useState<{ fields: MarketplaceFieldState; location: string } | null>(null)

  const productQuery = useQuery({
    queryKey: ["admin", "product-marketplace-details", data.id],
    queryFn: async () => {
      const response = await sdk.fetch(`/admin/products/${data.id}/waste`)

      if (!response.ok) {
        throw new Error(t("biomketProduct.marketplace.loadError"))
      }

      return (await response.json()) as ProductResponse
    },
  })

  const locationsQuery = useQuery({
    queryKey: ["admin", "locations", "dropdown"],
    queryFn: async () => {
      const response = await sdk.fetch("/admin/locations", { method: "GET" })

      if (!response.ok) {
        throw new Error(t("biomketProduct.marketplace.loadError"))
      }

      const json = (await response.json()) as { locations?: LocationRecord[] }
      return Array.isArray(json.locations) ? json.locations : []
    },
  })

  useEffect(() => {
    const product = productQuery.data?.product
    if (!product) {
      return
    }

    const md = product.marketplace_detail
    const meta = product.metadata || {}
    const currentQty = product.current_available_quantity ?? null

    // Use saved value only if it is a manual override (On Request / Recurring Supply).
    // Otherwise always reflect real inventory: qty > 0 → In Stock, else Out of Stock.
    const savedAvailability = (md?.availability ?? "") as AvailabilityValue
    const autoAvailability: AvailabilityValue = isManualStatus(savedAvailability)
      ? savedAvailability
      : currentQty != null
      ? currentQty > 0
        ? "In Stock"
        : "Out of Stock"
      : savedAvailability || "Out of Stock"

    const nextFields = {
      availability: autoAvailability,
      available_quantity: md?.available_quantity || findMetadataValue(meta, ["available quantity", "available_quantity"]),
      supply_frequency: md?.supply_frequency || findMetadataValue(meta, ["supply frequency", "supply_frequency"]),
      waste_type: md?.waste_type || findMetadataValue(meta, ["waste type", "waste_type"]),
      unit: md?.unit || findMetadataValue(meta, ["unit", "Unit"]),
    }
    const savedFields = {
      ...nextFields,
      availability: savedAvailability || autoAvailability,
    }
    const nextLocation = typeof md?.location === "string" ? md.location : ""

    setFields(nextFields)
    setLocation(nextLocation)
    setLastSaved({ fields: normalizeValue(savedFields), location: normalizeValue(nextLocation) })
  }, [productQuery.data])

  const saveMutation = useMutation({
    mutationFn: async (payload: MarketplaceFieldState & { location: string }) => {
      const response = await sdk.fetch(`/admin/products/${data.id}/waste`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const error = await response.text()
        throw new Error(error || t("biomketProduct.marketplace.saveError"))
      }

      return payload
    },
    onSuccess: (payload) => {
      queryClient.setQueryData<ProductResponse>(
        ["admin", "product-marketplace-details", data.id],
        (current) => ({
          product: {
            ...current?.product!,
            marketplace_detail: {
              ...current?.product?.marketplace_detail,
              ...payload,
            },
          },
        })
      )
      toast.success(t("biomketProduct.marketplace.saveSuccess"))
      setLastSaved({ fields: normalizeValue(payload), location: normalizeValue(payload.location) })
      queryClient.invalidateQueries({
        queryKey: ["admin", "product-marketplace-details", data.id],
      })
    },
    onError: (error: Error) => {
      toast.error(error.message || t("biomketProduct.marketplace.saveError"))
    },
  })

  // Current inventory quantity (for display)
  const currentAvailableQty = productQuery.data?.product?.current_available_quantity ?? null

  const availabilityOptions = AVAILABILITY_VALUES.map((val) => ({
    label:
      val === "In Stock"
        ? t("biomketProduct.marketplace.inStock")
        : val === "Out of Stock"
        ? t("biomketProduct.marketplace.outOfStock")
        : val === "Recurring Supply"
        ? t("biomketProduct.marketplace.recurringSupply")
        : t("biomketProduct.marketplace.onRequest"),
    value: val,
  }))

  const unitOptions = [
    { label: t("biomketProduct.marketplace.unitTonne"), value: "t" },
    { label: t("biomketProduct.marketplace.unitKilogram"), value: "kg" },
    { label: t("biomketProduct.marketplace.unitLiter"), value: "L" },
    { label: t("biomketProduct.marketplace.unitCubicMeter"), value: "m³" },
  ]

  const locations = locationsQuery.data ?? []
  const flattenedOptions = locations.flatMap((parent) => {
    const baseOption = { id: parent.id, label: parent.name, value: parent.name }
    const subOptions = parent.sub_locations.map((subLocation) => ({
      id: subLocation.id,
      label: `${subLocation.name}, ${parent.name}`,
      value: `${subLocation.name}, ${parent.name}`,
    }))

    return [baseOption, ...subOptions]
  })

  const includesCurrentLocation = flattenedOptions.some(
    (option) => option.value === location
  )
  const allLocationOptions =
    location && !includesCurrentLocation
      ? [{ id: "__current__", label: location, value: location }, ...flattenedOptions]
      : flattenedOptions
  const includesCurrentUnit = unitOptions.some(
    (option) => option.value === fields.unit
  )
  const allUnitOptions =
    fields.unit && !includesCurrentUnit
      ? [{ label: fields.unit, value: fields.unit }, ...unitOptions]
      : unitOptions

  if (productQuery.isLoading || locationsQuery.isLoading) {
    return (
      <Container className="px-6 py-4">
        <Text size="small" leading="compact" className="text-ui-fg-subtle">
          {t("biomketProduct.marketplace.loading")}
        </Text>
      </Container>
    )
  }

  if (productQuery.isError || locationsQuery.isError) {
    return (
      <Container className="px-6 py-4">
        <Text size="small" leading="compact" className="text-ui-fg-error">
          {t("biomketProduct.marketplace.loadError")}
        </Text>
      </Container>
    )
  }

  const isDirty = lastSaved != null && (
    !isContentEqual(fields, lastSaved.fields) ||
    !isContentEqual(location, lastSaved.location)
  )

  return (
    <Container className="px-6 py-4">
      <div className="flex flex-col gap-y-1">
        <Text size="large" leading="compact" weight="plus">
          {t("biomketProduct.marketplace.title")}
        </Text>
        <Text size="small" leading="compact" className="text-ui-fg-subtle">
          {t("biomketProduct.marketplace.subtitle")}
        </Text>
      </div>

      <div className="mt-4 flex flex-col gap-y-4">
        {/* Availability Status — dropdown, auto-selects In Stock when qty > 0 */}
        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.availabilityStatus")}
          </Text>
          <Select
            value={fields.availability}
            onValueChange={(value) =>
              setFields((current) => ({ ...current, availability: value as AvailabilityValue }))
            }
          >
            <Select.Trigger>
              <Select.Value placeholder={t("biomketProduct.marketplace.selectAvailability")} />
            </Select.Trigger>
            <Select.Content>
              {availabilityOptions.map((option) => (
                <Select.Item key={option.value} value={option.value}>
                  {option.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select>
          {currentAvailableQty != null && (
            <Text size="xsmall" leading="compact" className="text-ui-fg-subtle">
              {t("biomketProduct.marketplace.currentQtyHint", { count: currentAvailableQty })}  
            </Text>
          )}
        </div>

        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.unitOfMeasurement")}
          </Text>
          <Select
            value={fields.unit}
            onValueChange={(value) =>
              setFields((current) => ({ ...current, unit: value }))
            }
          >
            <Select.Trigger>
              <Select.Value placeholder={t("biomketProduct.marketplace.selectUnit")} />
            </Select.Trigger>
            <Select.Content>
              {allUnitOptions.map((option) => (
                <Select.Item key={option.value} value={option.value}>
                  {option.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select>
        </div>

        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.availableQuantity")}
          </Text>
          <Input
            value={fields.available_quantity}
            placeholder={t("biomketProduct.marketplace.quantityPlaceholder")}
            onChange={(event) =>
              setFields((current) => ({
                ...current,
                available_quantity: event.target.value,
              }))
            }
          />
        </div>

        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.supplyFrequency")}
          </Text>
          <Input
            value={fields.supply_frequency}
            placeholder={t("biomketProduct.marketplace.supplyFrequencyPlaceholder")}
            onChange={(event) =>
              setFields((current) => ({
                ...current,
                supply_frequency: event.target.value,
              }))
            }
          />
        </div>

        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.productLocation")}
          </Text>
          <Select value={location} onValueChange={setLocation}>
            <Select.Trigger>
              <Select.Value placeholder={t("biomketProduct.marketplace.selectLocation")} />
            </Select.Trigger>
            <Select.Content>
              {allLocationOptions.map((option) => (
                <Select.Item key={option.id} value={option.value}>
                  {option.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select>
        </div>

        <div className="flex flex-col gap-y-2">
          <Text size="small" leading="compact" weight="plus">
            {t("biomketProduct.marketplace.wasteType")}
          </Text>
          <Input
            value={fields.waste_type}
            placeholder={t("biomketProduct.marketplace.wasteTypePlaceholder")}
            onChange={(event) =>
              setFields((current) => ({
                ...current,
                waste_type: event.target.value,
              }))
            }
          />
        </div>


      </div>

      <div className="mt-6 flex justify-end">
        <Button
          size="small"
          isLoading={saveMutation.isPending}
          disabled={
            !isDirty
          }
          onClick={() =>
            saveMutation.mutate({
              ...fields,
              location,
            })
          }
        >
          {t("biomketProduct.common.save")}
        </Button>
      </div>
    </Container>
  )
}

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

export default ProductAvailabilityWidget
