import { defineRouteConfig } from "@medusajs/admin-sdk"
import { PencilSquare, PlusMini, Trash } from "@medusajs/icons"
import {
  Button,
  Container,
  Drawer,
  FocusModal,
  Input,
  Text,
  toast,
} from "@medusajs/ui"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { useState } from "react"
import { sdk } from "../../lib/sdk"
import { useTranslation } from "react-i18next"

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

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

type EditingState =
  | { kind: "location"; id: string; name: string }
  | { kind: "sub_location"; id: string; name: string }
  | null

const locationsQueryKey = ["admin", "locations"]

export const config = defineRouteConfig({
  label: "adminRoutes.locations.title",
  translationNs: "translation",
})

async function parseJsonOrThrow(response: Response) {
  const text = await response.text()

  if (!response.ok) {
    let message = text || "Request failed."

    try {
      const json = JSON.parse(text)
      if (json?.message) {
        message = json.message
      }
    } catch {
      // Keep text fallback
    }

    throw new Error(message)
  }

  return text ? JSON.parse(text) : {}
}

export default function LocationsPage() {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const [createOpen, setCreateOpen] = useState(false)
  const [newLocationName, setNewLocationName] = useState("")
  const [subLocationOpen, setSubLocationOpen] = useState(false)
  const [subLocationParent, setSubLocationParent] = useState<LocationRecord | null>(null)
  const [newSubLocationName, setNewSubLocationName] = useState("")
  const [editingItem, setEditingItem] = useState<EditingState>(null)
  const [editName, setEditName] = useState("")

  const locationsQuery = useQuery({
    queryKey: locationsQueryKey,
    queryFn: async () => {
      const response = await sdk.fetch("/admin/locations", { method: "GET" })
      const json = (await parseJsonOrThrow(response)) as { locations?: LocationRecord[] }
      return Array.isArray(json.locations) ? json.locations : []
    },
  })

  const invalidateLocations = () => {
    queryClient.invalidateQueries({ queryKey: locationsQueryKey })
  }

  const createLocation = useMutation({
    mutationFn: async (name: string) => {
      const response = await sdk.fetch("/admin/locations", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name }),
      })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.locationAdded"))
      setNewLocationName("")
      setCreateOpen(false)
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.locationAddError")),
  })

  const updateLocation = useMutation({
    mutationFn: async (payload: { id: string; name: string }) => {
      const response = await sdk.fetch(`/admin/locations/${payload.id}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: payload.name }),
      })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.locationUpdated"))
      setEditingItem(null)
      setEditName("")
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.locationUpdateError")),
  })

  const deleteLocation = useMutation({
    mutationFn: async (id: string) => {
      const response = await sdk.fetch(`/admin/locations/${id}`, { method: "DELETE" })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.locationDeleted"))
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.locationDeleteError")),
  })

  const createSubLocation = useMutation({
    mutationFn: async (payload: { locationId: string; name: string }) => {
      const response = await sdk.fetch(`/admin/locations/${payload.locationId}/sub-locations`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: payload.name }),
      })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.subLocationAdded"))
      setNewSubLocationName("")
      setSubLocationParent(null)
      setSubLocationOpen(false)
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.subLocationAddError")),
  })

  const updateSubLocation = useMutation({
    mutationFn: async (payload: { id: string; name: string }) => {
      const response = await sdk.fetch(`/admin/sub-locations/${payload.id}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: payload.name }),
      })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.subLocationUpdated"))
      setEditingItem(null)
      setEditName("")
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.subLocationUpdateError")),
  })

  const deleteSubLocation = useMutation({
    mutationFn: async (id: string) => {
      const response = await sdk.fetch(`/admin/sub-locations/${id}`, { method: "DELETE" })
      return parseJsonOrThrow(response)
    },
    onSuccess: () => {
      toast.success(t("adminRoutes.locations.toasts.subLocationDeleted"))
      invalidateLocations()
    },
    onError: (error: Error) => toast.error(error.message || t("adminRoutes.locations.toasts.subLocationDeleteError")),
  })

  const locations = locationsQuery.data ?? []

  return (
    <Container className="px-6 py-4">
      <div className="flex items-center justify-between gap-3">
        <div>
          <Text size="xlarge" weight="plus">{t("adminRoutes.locations.title")}</Text>
          <Text size="small" className="text-ui-fg-subtle">
            {t("adminRoutes.locations.subtitle")}
          </Text>
        </div>
        <Button size="small" variant="secondary" onClick={() => setCreateOpen(true)}>
          <PlusMini />
          {t("adminRoutes.locations.actions.addLocation")}
        </Button>
      </div>

      <div className="mt-6 rounded-lg border border-ui-border-base">
        {locationsQuery.isLoading ? (
          <div className="px-6 py-8">
            <Text size="small" className="text-ui-fg-subtle">{t("adminRoutes.locations.loading")}</Text>
          </div>
        ) : null}

        {locationsQuery.isError ? (
          <div className="px-6 py-8">
            <Text size="small" className="text-ui-fg-error">
              {(locationsQuery.error as Error)?.message || t("adminRoutes.locations.loadError")}
            </Text>
          </div>
        ) : null}

        {!locationsQuery.isLoading && !locationsQuery.isError && locations.length === 0 ? (
          <div className="px-6 py-8">
            <Text size="small" className="text-ui-fg-subtle">{t("adminRoutes.locations.empty")}</Text>
          </div>
        ) : null}

        {!locationsQuery.isLoading && !locationsQuery.isError && locations.length > 0 ? (
          <div className="divide-y divide-ui-border-base">
            {locations.map((location) => (
              <div key={location.id} className="px-6 py-5">
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <Text size="large" weight="plus">{location.name}</Text>
                  </div>
                  <div className="flex gap-2">
                    <Button
                      size="small"
                      variant="secondary"
                      onClick={() => {
                        setSubLocationParent(location)
                        setSubLocationOpen(true)
                      }}
                    >
                      <PlusMini />
                      {t("adminRoutes.locations.actions.addSubLocation")}
                    </Button>
                    <Button
                      size="small"
                      variant="secondary"
                      onClick={() => {
                        setEditingItem({ kind: "location", id: location.id, name: location.name })
                        setEditName(location.name)
                      }}
                    >
                      <PencilSquare />
                      {t("adminRoutes.common.edit")}
                    </Button>
                    <Button
                      size="small"
                      variant="secondary"
                      disabled={deleteLocation.isPending}
                      onClick={() => deleteLocation.mutate(location.id)}
                    >
                      <Trash />
                      {t("adminRoutes.common.delete")}
                    </Button>
                  </div>
                </div>

                <div className="mt-4 flex flex-col gap-2 pl-4">
                  {location.sub_locations.length === 0 ? (
                    <Text size="small" className="text-ui-fg-subtle">{t("adminRoutes.locations.emptySubLocations")}</Text>
                  ) : (
                    location.sub_locations.map((subLocation) => (
                      <div
                        key={subLocation.id}
                        className="flex items-center justify-between rounded-md border border-ui-border-base px-4 py-3"
                      >
                        <div>
                          <Text size="small" weight="plus">{subLocation.name}</Text>
                        </div>
                        <div className="flex gap-2">
                          <Button
                            size="small"
                            variant="secondary"
                            onClick={() => {
                              setEditingItem({ kind: "sub_location", id: subLocation.id, name: subLocation.name })
                              setEditName(subLocation.name)
                            }}
                          >
                            <PencilSquare />
                            {t("adminRoutes.common.edit")}
                          </Button>
                          <Button
                            size="small"
                            variant="secondary"
                            disabled={deleteSubLocation.isPending}
                            onClick={() => deleteSubLocation.mutate(subLocation.id)}
                          >
                            <Trash />
                            {t("adminRoutes.common.delete")}
                          </Button>
                        </div>
                      </div>
                    ))
                  )}
                </div>
              </div>
            ))}
          </div>
        ) : null}
      </div>

      <FocusModal open={createOpen} onOpenChange={setCreateOpen}>
        <FocusModal.Content>
          <div className="flex h-full flex-col overflow-hidden">
            <FocusModal.Header>
              <div className="flex items-center justify-end gap-2">
                <FocusModal.Close asChild>
                  <Button size="small" variant="secondary" disabled={createLocation.isPending}>Cancel</Button>
                </FocusModal.Close>
                <Button size="small" isLoading={createLocation.isPending} onClick={() => createLocation.mutate(newLocationName)}>
                  {t("adminRoutes.common.save")}
                </Button>
              </div>
            </FocusModal.Header>
            <FocusModal.Body className="flex-1 overflow-auto">
              <div className="mx-auto flex w-full max-w-xl flex-col gap-4 px-6 py-8">
                <Text size="xlarge" weight="plus">{t("adminRoutes.locations.actions.addLocation")}</Text>
                <Input
                  value={newLocationName}
                  onChange={(event) => setNewLocationName(event.target.value)}
                  placeholder="Andalusia"
                />
              </div>
            </FocusModal.Body>
          </div>
        </FocusModal.Content>
      </FocusModal>

      <FocusModal open={subLocationOpen} onOpenChange={setSubLocationOpen}>
        <FocusModal.Content>
          <div className="flex h-full flex-col overflow-hidden">
            <FocusModal.Header>
              <div className="flex items-center justify-end gap-2">
                <FocusModal.Close asChild>
                  <Button size="small" variant="secondary" disabled={createSubLocation.isPending}>Cancel</Button>
                </FocusModal.Close>
                <Button
                  size="small"
                  isLoading={createSubLocation.isPending}
                  onClick={() => {
                    if (!subLocationParent) return
                    createSubLocation.mutate({
                      locationId: subLocationParent.id,
                      name: newSubLocationName,
                    })
                  }}
                >
                  {t("adminRoutes.common.save")}
                </Button>
              </div>
            </FocusModal.Header>
            <FocusModal.Body className="flex-1 overflow-auto">
              <div className="mx-auto flex w-full max-w-xl flex-col gap-4 px-6 py-8">
                <Text size="xlarge" weight="plus">{t("adminRoutes.locations.actions.addSubLocation")}</Text>
                <Text size="small" className="text-ui-fg-subtle">
                  {t("adminRoutes.locations.parentLabel")} {subLocationParent?.name || "-"}
                </Text>
                <Input
                  value={newSubLocationName}
                  onChange={(event) => setNewSubLocationName(event.target.value)}
                  placeholder="Almería"
                />
              </div>
            </FocusModal.Body>
          </div>
        </FocusModal.Content>
      </FocusModal>

      <Drawer
        open={Boolean(editingItem)}
        onOpenChange={(open) => {
          if (!open) {
            setEditingItem(null)
            setEditName("")
          }
        }}
      >
        <Drawer.Content>
          <Drawer.Header>
            <Drawer.Title>
              {editingItem?.kind === "sub_location"
                ? t("adminRoutes.locations.actions.editSubLocation")
                : t("adminRoutes.locations.actions.editLocation")}
            </Drawer.Title>
          </Drawer.Header>
          <Drawer.Body className="flex flex-1 flex-col gap-4 p-4">
            <Input value={editName} onChange={(event) => setEditName(event.target.value)} />
          </Drawer.Body>
          <Drawer.Footer>
            <div className="flex items-center justify-end gap-2">
              <Drawer.Close asChild>
                <Button size="small" variant="secondary">Cancel</Button>
              </Drawer.Close>
              <Button
                size="small"
                isLoading={updateLocation.isPending || updateSubLocation.isPending}
                onClick={() => {
                  if (!editingItem) return

                  if (editingItem.kind === "location") {
                    updateLocation.mutate({ id: editingItem.id, name: editName })
                    return
                  }

                  updateSubLocation.mutate({ id: editingItem.id, name: editName })
                }}
              >
                {t("adminRoutes.common.save")}
              </Button>
            </div>
          </Drawer.Footer>
        </Drawer.Content>
      </Drawer>
    </Container>
  )
}
