'use client';
import React, { useEffect } from 'react';
import { useTranslations } from "next-intl";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { PostMediaData } from '@/lib/database';
import { useForm, Controller, Control } from 'react-hook-form';
import { Form } from "react-compose-form";
import { zodResolver } from '@hookform/resolvers/zod';
import z from 'zod';
import { toast } from 'sonner';
import { FormMessage } from "@/components/form/form-message";
import { WidgetPosition } from '@/config/enums/tip-tap';
import { InputControl } from "@/components/form/control/input.control";
import { useMediaPicker } from "@/components/ui/media-picker";
import { MediaPreview } from "@/components/dashboard/media/media-preview";
import { SelectControl } from "@/components/form/control/select.control";
import { api } from "@/lib/trpc/client";
import { MediaScope } from "@/server/modules/media/types/media-scope.enum";

const schema = z.object({
  variant: z.nativeEnum(WidgetPosition),
  caption: z.string(),
  author: z.string(),
  labelBefore: z.string().min(1),
  mediaBefore: z
    .array(
      z.custom<PostMediaData>()
      // z.object({
      //   id: z.string().uuid(),
      //   url: z.string(),
      //   alt: z.string(),
      //   caption: z.string().nullable(),
      //   author: z.string().nullable()
      // })
    )
    .min(1, 'Before image is required'),

  labelAfter: z.string().min(1),
  mediaAfter: z
    .array(z.custom<PostMediaData>())
    .min(1, 'After image is required')
}).superRefine((data, ctx) => {
  if(!data.mediaBefore || !data.mediaBefore[0]?.id) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "Before image is required",
      path: ["mediaBefore"]
    });
  }

  if(!data.mediaAfter || !data.mediaAfter[0]?.id) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "After image is required",
      path: ["mediaAfter"]
    });
  }
});

type BeforeAfterForm = z.infer<typeof schema>;

const options = [
  {
    label: 'Default',
    value: WidgetPosition.CENTER
  },
  {
    label: 'Full Width',
    value: WidgetPosition.FULL
  },
  {
    label: '2/3 Width',
    value: WidgetPosition.ALIGN_LEFT
  }
];

const defaultValues: BeforeAfterForm = {
  variant: WidgetPosition.CENTER,
  caption: '',
  author: '',
  labelBefore: 'Før',
  mediaBefore: [],
  labelAfter: 'Efter',
  mediaAfter: []
};

type Props = {
  open: boolean;
  onOpenChange: (v: boolean) => void;
  initialValues?: BeforeAfterForm;
  onSubmit: (data: BeforeAfterForm) => void;
  title: string;
  description: string;
};

export function BeforeAfterImageDialog({
  open,
  onOpenChange,
  initialValues,
  onSubmit,
  title,
  description
}: Props) {
  const form = useForm<BeforeAfterForm>({
    resolver: zodResolver(schema),
    defaultValues: initialValues ?? defaultValues,
    mode: 'onChange'
  });
  const {
    setValue,
    reset,
    control,
    handleSubmit
  } = form;

  const t = useTranslations();
  const mediaPicker = useMediaPicker();
  const utils = api.useUtils();

  useEffect(() => {
    if (open) {
      reset(initialValues ?? defaultValues);
    }
  }, [open, initialValues, reset]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>{description}</DialogDescription>
        </DialogHeader>

        <Form
          className="contents"
          formControl={form}
          resolver={zodResolver(schema)}
        >
          <div className='flex max-h-[70vh] flex-col gap-3 overflow-y-auto'>
            <div className='flex flex-col gap-2'>
              <SelectControl
                control={control as unknown as Control}
                label={t("dashboard.tiptap.beforeAfterImage.fields.variant.label")}
                name="variant"
              >
                <SelectControl.Trigger>
                  <SelectControl.Value placeholder={t('dashboard.tiptap.beforeAfterImage.fields.variant.placeholder')} />
                </SelectControl.Trigger>

                <SelectControl.Content>
                  <SelectControl.Group>
                    {options.map((option) => (
                      <SelectControl.Item key={option.value} value={option.value}>
                        {option.label}
                      </SelectControl.Item>
                    ))}
                  </SelectControl.Group>
                </SelectControl.Content>
              </SelectControl>
            </div>

            <div className="flex gap-2 flex-row">
              <div className="flex-0">
                <Controller
                  name='mediaBefore'
                  control={control}
                  render={({ field }) => {
                    const selected = field.value?.[0];

                    const handleSelect = (media: PostMediaData[]) => {
                      const first = media[0];

                      if (!first) {
                        field.onChange([]);
                        return;
                      }

                      const alt = first.alt || "";

                      field.onChange([
                        {
                          ...first,
                          alt
                        }
                      ]);

                      if(alt) {
                        setValue("mediaBefore.0.alt", alt);
                      }
                    };

                    const handlePick = async () => {
                      const [id] = await mediaPicker.pick({
                        withAttachments: true,
                        autosubmit: true,
                        scope: MediaScope.POST,
                        selected: selected ? [selected.id] : [],
                        defaultAttached: true
                      });

                      if(!id) {
                        handleSelect([]);
                        return;
                      }

                      const media = await utils.media.get.fetch({ id });

                      handleSelect(media ? [media] : []);
                    };

                    return (
                      <div>
                        <MediaPreview
                          {...selected}
                          size={150}
                          author={selected?.author || ""}
                          caption={selected?.caption || ""}
                          alt={selected?.alt || ""}
                          onEdit={handlePick} />

                        <FormMessage absolute name={field.name} />
                      </div>
                    );
                  }}
                />
              </div>

              <div className="flex-1 flex flex-col gap-2">
                <InputControl
                  control={control as unknown as Control}
                  label={t("dashboard.tiptap.beforeAfterImage.fields.beforeImage.label")}
                  placeholder={t("dashboard.tiptap.beforeAfterImage.fields.beforeImage.placeholder")}
                  name="labelBefore" />

                <InputControl
                  control={control as unknown as Control}
                  label={t("dashboard.media.editor.fields.alt.label")}
                  placeholder={t("dashboard.media.editor.fields.alt.placeholder")}
                  name="mediaBefore.0.alt" />
              </div>
            </div>

            <div className="flex gap-2 flex-row">
              <div className="flex-0">
                <Controller
                  control={control}
                  name='mediaAfter'
                  render={({ field }) => {
                    const selected = field.value?.[0];
                    const handleSelect = (media: PostMediaData[]) => {
                      const first = media[0];

                      if (!first) {
                        field.onChange([]);
                        return;
                      }

                      const alt = first.alt || "";

                      field.onChange([
                        {
                          ...first,
                          alt
                        }
                      ]);

                      if(alt) {
                        setValue("mediaAfter.0.alt", alt);
                      }
                    };

                    const handlePick = async () => {
                      const [id] = await mediaPicker.pick({
                        withAttachments: true,
                        autosubmit: true,
                        scope: MediaScope.POST,
                        selected: selected ? [selected.id] : [],
                        defaultAttached: true
                      });

                      if(!id) {
                        handleSelect([]);
                        return;
                      }

                      const media = await utils.media.get.fetch({ id });

                      handleSelect(media ? [media] : []);
                    };

                    return (
                      <div>
                        <MediaPreview
                          {...selected}
                          size={150}
                          author={selected?.author || ""}
                          caption={selected?.caption || ""}
                          alt={selected?.alt || ""}
                          onEdit={handlePick} />

                        <FormMessage absolute name={field.name} />
                      </div>
                    );
                  }}
                />
              </div>

              <div className="flex-1 flex flex-col gap-2">
                <InputControl
                  control={control as unknown as Control}
                  label={t("dashboard.tiptap.beforeAfterImage.fields.afterImage.label")}
                  placeholder={t("dashboard.tiptap.beforeAfterImage.fields.afterImage.placeholder")}
                  name="labelAfter" />

                <InputControl
                  control={control as unknown as Control}
                  label={t("dashboard.media.editor.fields.alt.label")}
                  placeholder={t("dashboard.media.editor.fields.alt.placeholder")}
                  name="mediaAfter.0.alt" />
              </div>
            </div>

            <InputControl
              control={control as unknown as Control}
              label={t("dashboard.tiptap.beforeAfterImage.fields.caption.label")}
              placeholder={t("dashboard.tiptap.beforeAfterImage.fields.caption.placeholder")}
              name="caption" />

            <InputControl
              control={control as unknown as Control}
              label={t("dashboard.tiptap.beforeAfterImage.fields.author.label")}
              placeholder={t("dashboard.tiptap.beforeAfterImage.fields.author.placeholder")}
              name="author" />
          </div>

          <DialogFooter>
            <Button
              type='button'
              variant='outline'
              onClick={() => {
                onOpenChange(false);
                reset(defaultValues);
              }}
            >
              {t("dashboard.general.actions.cancel")}
            </Button>
            <Button
              type='button'
              onClick={handleSubmit(onSubmit, () => {
                toast.error(t("dashboard.tiptap.beforeAfterImage.fields.media.error"));
              })}
            >
              {t("dashboard.general.actions.save")}
            </Button>
          </DialogFooter>
        </Form>
      </DialogContent>
    </Dialog>
  );
}
