"use client"

import { z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { useTranslations } from "next-intl"
import { toast } from "sonner"

import { QueryState } from "@/components/api/query-state"
import { EditDangerSection } from "@/components/edit-danger-section"
import { MediaFileField } from "@/components/markatty/media-file-field"
import { FormSection } from "@/components/form-section"
import { PageHeader } from "@/components/page-header"
import { Button } from "@/components/ui/button"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
  useClient,
  useClients,
  useCreateClient,
  useDeleteClient,
  useUpdateClient,
} from "@/hooks/api/use-clients"
import { useRouter } from "@/i18n/navigation"
import {
  clientPairToFormValues,
  displayClientLink,
  ensurePairLink,
  findClientSibling,
  type ClientInput,
} from "@/lib/api/clients"
import { ApiError } from "@/lib/api/errors"
import type { ClientRecord } from "@/lib/markatty"

const clientSchema = z.object({
  name: z.string().min(2, "Client name is required."),
  categoryEn: z.string(),
  categoryAr: z.string(),
  link: z
    .string()
    .refine(
      (value) =>
        !value.trim() ||
        value.trim().startsWith("pair:") ||
        z.string().url().safeParse(value.trim()).success,
      "Enter a valid URL."
    ),
  logoFile: z.any().optional(),
})

type ClientFormValues = z.infer<typeof clientSchema>

function toLocaleInput(
  values: ClientFormValues,
  locale: "en" | "ar",
  link: string,
  logoFile: File | null
): ClientInput {
  return {
    name: values.name,
    category: locale === "ar" ? values.categoryAr : values.categoryEn,
    link,
    locale,
    logoFile,
  }
}

function ClientEditorForm({
  mode,
  enClient,
  arClient,
}: {
  mode: "create" | "edit"
  enClient?: ClientRecord
  arClient?: ClientRecord
}) {
  const t = useTranslations("Clients")
  const tCreate = useTranslations("Clients.Create")
  const tEdit = useTranslations("Clients.Edit")
  const tc = useTranslations("Common")
  const router = useRouter()
  const createClient = useCreateClient()
  const updateClient = useUpdateClient()
  const deleteClient = useDeleteClient()

  const previewClient = enClient ?? arClient
  const existingPairLink = enClient?.link || arClient?.link || ""
  const formValues = {
    ...clientPairToFormValues(enClient, arClient),
    link: displayClientLink(existingPairLink),
  }

  const form = useForm<ClientFormValues>({
    resolver: zodResolver(clientSchema),
    defaultValues: formValues,
    values: mode === "edit" ? formValues : undefined,
  })

  const isPending =
    createClient.isPending ||
    updateClient.isPending ||
    deleteClient.isPending

  const displayName = enClient?.name || arClient?.name || ""

  const showApiError = (e: unknown) => {
    toast.error(e instanceof ApiError ? e.message : tc("api.errorFallback"))
  }

  async function saveLocale(
    values: ClientFormValues,
    locale: "en" | "ar",
    existing: ClientRecord | undefined,
    link: string,
    logoFile: File | null
  ) {
    const input = toLocaleInput(values, locale, link, logoFile)
    if (existing) {
      await updateClient.mutateAsync({ id: existing.id, ...input })
      return
    }
    await createClient.mutateAsync(input)
  }

  async function onSubmit(values: ClientFormValues) {
    const logoFile = values.logoFile instanceof File ? values.logoFile : null
    const link = ensurePairLink(values.link, existingPairLink)

    try {
      if (mode === "create") {
        await createClient.mutateAsync(toLocaleInput(values, "en", link, logoFile))
        await createClient.mutateAsync(toLocaleInput(values, "ar", link, logoFile))
        toast.success(t("toast.created"))
      } else {
        await saveLocale(values, "en", enClient, link, logoFile)
        await saveLocale(values, "ar", arClient, link, logoFile)
        toast.success(t("toast.updated"))
      }
      router.back()
    } catch (e) {
      showApiError(e)
    }
  }

  async function handleDelete() {
    try {
      const ids = [enClient?.id, arClient?.id].filter(
        (id): id is string => Boolean(id)
      )
      for (const id of ids) {
        await deleteClient.mutateAsync(id)
      }
      toast.success(t("toast.deleted"))
      router.back()
    } catch (e) {
      showApiError(e)
    }
  }

  return (
    <div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
      <PageHeader
        title={
          mode === "create"
            ? tCreate("title")
            : tEdit("title", { name: displayName })
        }
        actions={
          <Button variant="outline" type="button" onClick={() => router.back()}>
            {tc("actions.back")}
          </Button>
        }
      />

      <Form {...form}>
        <form className="grid gap-6" onSubmit={form.handleSubmit(onSubmit)}>
          <FormSection title={tCreate("sections.content")}>
            <div className="grid gap-4 md:grid-cols-2">
              <FormField
                control={form.control}
                name="name"
                render={({ field }) => (
                  <FormItem className="md:col-span-2">
                    <FormLabel>{tCreate("labels.name")}</FormLabel>
                    <FormControl>
                      <Input
                        placeholder={tCreate("placeholders.name")}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="categoryEn"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{tCreate("labels.categoryEn")}</FormLabel>
                    <FormControl>
                      <Input
                        placeholder={tCreate("placeholders.categoryEn")}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="categoryAr"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{tCreate("labels.categoryAr")}</FormLabel>
                    <FormControl>
                      <Input
                        dir="rtl"
                        placeholder={tCreate("placeholders.categoryAr")}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="link"
                render={({ field }) => (
                  <FormItem className="md:col-span-2">
                    <FormLabel>{tCreate("labels.link")}</FormLabel>
                    <FormControl>
                      <Input
                        placeholder={tCreate("placeholders.link")}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="logoFile"
                render={({ field }) => (
                  <MediaFileField
                    className="md:col-span-2"
                    label={tCreate("labels.logo")}
                    accept="image/*"
                    name={field.name}
                    onBlur={field.onBlur}
                    inputRef={field.ref}
                    onChange={field.onChange}
                    helperText={
                      mode === "create"
                        ? tCreate("help.logoFileOptional")
                        : tCreate("help.logoFileReplace")
                    }
                    currentText={
                      previewClient?.logoUrl
                        ? tCreate("help.currentFile", {
                            value: previewClient.logoUrl,
                          })
                        : undefined
                    }
                    previewUrl={previewClient?.logoUrl}
                    previewClassName="size-40"
                    selectedPreviewLabel={tCreate("labels.selectedLogo")}
                    currentPreviewLabel={tCreate("labels.currentLogo")}
                    previewKind="image"
                  />
                )}
              />
            </div>
          </FormSection>

          {mode === "edit" && (enClient || arClient) ? (
            <EditDangerSection
              sectionTitle={tEdit("sections.dangerZone")}
              actionTitle={tEdit("danger.deleteTitle")}
              actionDescription={tEdit("danger.deleteDescription")}
              confirmMessage={t("confirm.delete", { name: displayName })}
              actionLabel={tc("actions.delete")}
              disabled={isPending}
              isPending={deleteClient.isPending}
              onDelete={handleDelete}
            />
          ) : null}

          <div className="px-4 lg:px-6">
            <div className="flex items-center justify-end gap-2">
              <Button variant="outline" type="button" onClick={() => router.back()}>
                {tc("actions.cancel")}
              </Button>
              <Button type="submit" disabled={isPending}>
                {mode === "create" ? tc("actions.create") : tc("actions.saveChanges")}
              </Button>
            </div>
          </div>
        </form>
      </Form>
    </div>
  )
}

export function ClientEditor({
  mode,
  id,
}: {
  mode: "create" | "edit"
  id?: string
}) {
  const clientQuery = useClient(id ?? "")
  const clientsQuery = useClients()

  if (mode === "create") {
    return <ClientEditorForm mode="create" />
  }

  const isLoading = clientQuery.isLoading || clientsQuery.isLoading
  const isError = clientQuery.isError || clientsQuery.isError
  const error = clientQuery.error ?? clientsQuery.error
  const client = clientQuery.data
  const sibling =
    client && clientsQuery.data
      ? findClientSibling(clientsQuery.data, client)
      : undefined

  const enClient =
    client == null
      ? undefined
      : client.locale === "ar"
        ? sibling
        : client
  const arClient =
    client == null
      ? undefined
      : client.locale === "ar"
        ? client
        : sibling

  return (
    <QueryState isLoading={isLoading} isError={isError} error={error}>
      {client ? (
        <ClientEditorForm
          key={`${enClient?.id ?? "none"}-${arClient?.id ?? "none"}`}
          mode="edit"
          enClient={enClient}
          arClient={arClient}
        />
      ) : null}
    </QueryState>
  )
}
