import { defineRouteConfig } from "@medusajs/admin-sdk"
import { Container, Heading, Button, Input, Label, Hint } from "@medusajs/ui"
import { useState, useEffect } from "react"
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
import { useNavigate, useParams } from "react-router-dom"
import { sdk } from "../../../../lib/sdk"
import { showConfirm } from "../../../../lib/confirm"
import { CmsLanguageDropdown } from "../../../../components/CmsLanguageDropdown"

type Field = { id: string; label: string; api_key: string; field_type: string; required: boolean; position: number; validation_rules?: Record<string, unknown> }
type ComponentTypeDetailResponse = {
  component_type: Record<string, unknown>
  fields: Field[]
  is_production_mode?: boolean
}

export const config = defineRouteConfig({})

function reorderFieldIds(fieldIds: string[], fromIndex: number, toIndex: number) {
  const nextFieldIds = fieldIds.filter((_, index) => index !== fromIndex)
  nextFieldIds.splice(toIndex, 0, fieldIds[fromIndex])
  return nextFieldIds
}

export default function EditComponentType() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const qc = useQueryClient()
  const [showFieldForm, setShowFieldForm] = useState(false)
  const [editingFieldId, setEditingFieldId] = useState<string | null>(null)
  const [fieldLabel, setFieldLabel] = useState("")
  const [fieldApiKey, setFieldApiKey] = useState("")
  const [fieldType, setFieldType] = useState("text")
  const [fieldRequired, setFieldRequired] = useState(false)
  const [fieldError, setFieldError] = useState<string | null>(null)
  const [nestedComponentTypeId, setNestedComponentTypeId] = useState<string>("")
  const [reusable, setReusable] = useState(false)
  const [repeatable, setRepeatable] = useState(false)

  const { data } = useQuery({
    queryKey: ["component-type", id],
    queryFn: async () => {
      const r = await sdk.fetch(`/admin/component-types/${id}`)
      if (!r.ok) throw new Error("Failed")
      return r.json() as Promise<ComponentTypeDetailResponse>
    },
    enabled: !!id,
  })

  const { data: typesData } = useQuery({
    queryKey: ["component-types"],
    queryFn: async () => {
      const r = await sdk.fetch("/admin/component-types")
      if (!r.ok) throw new Error("Failed")
      return r.json() as Promise<{ component_types: { id: string; name: string; display_name: string }[] }>
    },
    enabled: !!id,
  })
  const allTypes = typesData?.component_types ?? []
  const nestedTypeOptions = allTypes.filter((t) => t.id !== id)

  const saveType = useMutation({
    mutationFn: async (body: { display_name?: string; description?: string; reusable?: boolean; repeatable?: boolean }) => {
      const r = await sdk.fetch(`/admin/component-types/${id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      })
      if (!r.ok) throw new Error(await r.text())
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["component-type", id] }),
  })

  const addField = useMutation({
    mutationFn: async () => {
      setFieldError(null)
      const body: { label: string; api_key: string; field_type: string; required: boolean; validation_rules?: Record<string, unknown> } = {
        label: fieldLabel,
        api_key: fieldApiKey || fieldLabel.toLowerCase().replace(/\s/g, "_"),
        field_type: fieldType,
        required: fieldRequired,
      }
      if (fieldType === "component" && nestedComponentTypeId) {
        body.validation_rules = { nested_component_type_id: nestedComponentTypeId }
      }
      const r = await sdk.fetch(`/admin/component-types/${id}/fields`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      })
      const text = await r.text()
      if (!r.ok) throw new Error(text || "Failed to add field")
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["component-type", id] })
      setShowFieldForm(false)
      setFieldLabel("")
      setFieldApiKey("")
      setNestedComponentTypeId("")
      setFieldError(null)
    },
    onError: (e: Error) => {
      const msg = e.message || "Failed to add field"
      setFieldError(msg.includes("unique") || msg.includes("duplicate") ? "API key must be unique within this component type." : msg)
    },
  })

  const updateField = useMutation({
    mutationFn: async (fieldId: string) => {
      setFieldError(null)
      const body: { label: string; api_key: string; field_type: string; required: boolean; validation_rules?: Record<string, unknown> } = {
        label: fieldLabel,
        api_key: fieldApiKey,
        field_type: fieldType,
        required: fieldRequired,
      }
      if (fieldType === "component" && nestedComponentTypeId) {
        body.validation_rules = { nested_component_type_id: nestedComponentTypeId }
      }
      const r = await sdk.fetch(`/admin/component-types/${id}/fields/${fieldId}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      })
      const text = await r.text()
      if (!r.ok) throw new Error(text || "Failed to update field")
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["component-type", id] })
      setEditingFieldId(null)
      setFieldError(null)
    },
    onError: (e: Error) => {
      const msg = e.message || "Failed to update field"
      setFieldError(msg.includes("unique") || msg.includes("duplicate") ? "API key must be unique within this component type." : msg)
    },
  })

  const deleteField = useMutation({
    mutationFn: async (fieldId: string) => {
      const r = await sdk.fetch(`/admin/component-types/${id}/fields/${fieldId}`, { method: "DELETE" })
      if (!r.ok) throw new Error(await r.text())
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["component-type", id] }),
  })

  const reorder = useMutation({
    mutationFn: async (fieldIds: string[]) => {
      const r = await sdk.fetch(`/admin/component-types/${id}/fields/reorder`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ field_ids: fieldIds }),
      })
      if (!r.ok) throw new Error(await r.text())
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["component-type", id] }),
  })

  const type = data?.component_type as { name?: string; display_name?: string; description?: string; reusable?: boolean; repeatable?: boolean } | undefined
  const fields = (data?.fields ?? []) as Field[]
  const sorted = [...fields].sort((a, b) => a.position - b.position)
  // TEMPORARY: Disabled production mode check for editing
  // const isProductionMode = Boolean(data?.is_production_mode)
  const isProductionMode = false

  useEffect(() => {
    const f = editingFieldId ? fields.find((x) => x.id === editingFieldId) : null
    if (f) {
      setFieldLabel(f.label)
      setFieldApiKey(f.api_key)
      setFieldType(f.field_type)
      setFieldRequired(f.required)
      const nestedId = (f.validation_rules as { nested_component_type_id?: string } | undefined)?.nested_component_type_id ?? ""
      setNestedComponentTypeId(nestedId)
    } else {
      setNestedComponentTypeId("")
    }
  }, [editingFieldId, fields])

  useEffect(() => {
    if (type) {
      setReusable(!!type.reusable)
      setRepeatable(!!type.repeatable)
    }
  }, [type])

  if (!data) return <Container><p>Loading...</p></Container>

  return (
    <Container className="px-3 sm:px-4 overflow-x-hidden">
      <CmsLanguageDropdown />
      <div className="flex flex-col sm:flex-row sm:justify-between sm:items-center py-4 sm:py-6 gap-4">
        <Heading level="h1" className="text-xl sm:text-2xl truncate min-w-0">{(type as { display_name?: string })?.display_name ?? id}</Heading>
        <Button variant="secondary" onClick={() => navigate("/component-builder")} className="w-full sm:w-auto">Back</Button>
      </div>
      {isProductionMode && (
        <div className="mb-4 rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 max-w-2xl">
          <p className="text-sm text-ui-fg-subtle">
            Production mode is active. This component type is view-only, so fields and settings cannot be changed.
          </p>
        </div>
      )}
      <div className="grid gap-4 sm:gap-6 w-full max-w-2xl mb-6 sm:mb-8">
        <div className="min-w-0">
          <Label>Name (API key)</Label>
          <Input value={type?.name ?? ""} readOnly disabled className="w-full bg-ui-bg-subtle" />
          <Hint className="mt-1">Cannot be changed after creation.</Hint>
        </div>
        <div className="min-w-0">
          <Label>Display name</Label>
          <Input defaultValue={type?.display_name} disabled={isProductionMode} readOnly={isProductionMode} onBlur={(e) => saveType.mutate({ display_name: e.target.value })} className={`w-full ${isProductionMode ? "bg-ui-bg-subtle" : ""}`} />
        </div>
        <div className="min-w-0">
          <Label>Description</Label>
          <Input defaultValue={type?.description} disabled={isProductionMode} readOnly={isProductionMode} onBlur={(e) => saveType.mutate({ description: e.target.value })} className={`w-full ${isProductionMode ? "bg-ui-bg-subtle" : ""}`} />
        </div>
        <div className="flex flex-wrap gap-6">
          <label className="flex items-center gap-2">
            <input
              type="checkbox"
              checked={reusable}
              disabled={isProductionMode}
              onChange={(e) => {
                const v = e.target.checked
                setReusable(v)
                saveType.mutate({ reusable: v })
              }}
            />
            <span>Reusable</span>
          </label>
          <label className="flex items-center gap-2">
            <input
              type="checkbox"
              checked={repeatable}
              disabled={isProductionMode}
              onChange={(e) => {
                const v = e.target.checked
                setRepeatable(v)
                saveType.mutate({ repeatable: v })
              }}
            />
            <span>Repeatable</span>
          </label>
        </div>
      </div>
      <Heading level="h2" className="mb-4 text-lg">Fields</Heading>
      {!isProductionMode && !showFieldForm && !editingFieldId && (
        <Button className="mb-4 w-full sm:w-auto" onClick={() => setShowFieldForm(true)}>Add field</Button>
      )}
      {!isProductionMode && (showFieldForm || editingFieldId) && (
        <div className="border p-3 sm:p-4 rounded mb-4 w-full max-w-md">
          {fieldError && (
            <div className="p-2 rounded bg-red-100 text-red-800 text-sm mb-3" role="alert">{fieldError}</div>
          )}
          <Label>Label</Label>
          <Input value={fieldLabel} onChange={(e) => setFieldLabel(e.target.value)} placeholder="e.g. Heading" className="mb-2" />
          <Label>API key — unique in this component</Label>
          <Input value={fieldApiKey} onChange={(e) => setFieldApiKey(e.target.value.replace(/\s/g, "_").toLowerCase())} placeholder="e.g. heading, main_image" className="mb-1" />
          <Hint className="mb-2">Lowercase, no spaces. Must be unique within this component type.</Hint>
          <Label>Type</Label>
          <select value={fieldType} onChange={(e) => { setFieldType(e.target.value); if (e.target.value !== "component") setNestedComponentTypeId(""); }} className="w-full border rounded px-2 py-1 mb-2">
            <option value="text">text</option>
            <option value="textarea">textarea</option>
            <option value="richtext">richtext</option>
            <option value="number">number</option>
            <option value="boolean">boolean</option>
            <option value="url">url</option>
            <option value="email">email</option>
            <option value="image">image</option>
            <option value="json">json</option>
            <option value="component">component (nested)</option>
          </select>
          {fieldType === "component" && (
            <div className="mb-2">
              <Label>Nested component type</Label>
              <select
                value={nestedComponentTypeId}
                onChange={(e) => setNestedComponentTypeId(e.target.value)}
                className="w-full border rounded px-2 py-1.5 bg-ui-bg-field border-ui-border-base"
              >
                <option value="">Select a component type</option>
                {nestedTypeOptions.map((t) => (
                  <option key={t.id} value={t.id}>{t.display_name || t.name}</option>
                ))}
              </select>
              <Hint className="mt-1">This field will contain an instance of the selected component type.</Hint>
            </div>
          )}
          <label className="flex items-center gap-2 mb-2">
            <input type="checkbox" checked={fieldRequired} onChange={(e) => setFieldRequired(e.target.checked)} />
            Required
          </label>
          <div className="flex flex-col sm:flex-row gap-2">
            {editingFieldId ? (
              <Button onClick={() => updateField.mutate(editingFieldId)} className="w-full sm:w-auto">Save</Button>
            ) : (
              <Button onClick={() => addField.mutate()} className="w-full sm:w-auto">Add</Button>
            )}
            <Button variant="secondary" onClick={() => { setShowFieldForm(false); setEditingFieldId(null); }} className="w-full sm:w-auto">Cancel</Button>
          </div>
        </div>
      )}
      <ul className="divide-y min-w-0">
        {sorted.map((f, i) => (
          <li key={f.id} className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 py-2 min-w-0">
            <span className="text-sm sm:text-base truncate min-w-0">
              {f.label} ({f.api_key}) — {f.field_type === "component" ? (() => {
              const nestedId = (f.validation_rules as { nested_component_type_id?: string } | undefined)?.nested_component_type_id
              const nestedName = nestedId ? (allTypes.find((t) => t.id === nestedId)?.display_name ?? nestedId) : null
              return nestedName ? `component (nested: ${nestedName})` : "component (nested)"
            })() : f.field_type}{f.required ? " *" : ""}
            </span>
            <div className="flex gap-1 flex-shrink-0">
              {!isProductionMode && (
                <>
                  <Button size="small" variant="transparent" onClick={() => reorder.mutate(reorderFieldIds(sorted.map((x) => x.id), i, Math.max(0, i - 1)))}>↑</Button>
                  <Button size="small" variant="transparent" onClick={() => reorder.mutate(reorderFieldIds(sorted.map((x) => x.id), i, Math.min(sorted.length - 1, i + 1)))}>↓</Button>
                  <Button size="small" variant="secondary" onClick={() => setEditingFieldId(f.id)}>Edit</Button>
                  <Button size="small" variant="secondary" onClick={() => showConfirm({ title: "Delete field?", text: "This cannot be undone." }).then((r) => r.isConfirmed && deleteField.mutate(f.id))}>Delete</Button>
                </>
              )}
            </div>
          </li>
        ))}
      </ul>
    </Container>
  )
}
