/* eslint-disable @next/next/no-img-element */
'use client';

import { type ChangeEvent, useEffect, useRef, useState } from 'react';

import { useTranslations } from 'next-intl';

import { Loader2, UploadCloud, X } from 'lucide-react';
import { Control, useController } from 'react-hook-form';

import * as Field from '@/components/forms/Field';
import { Button } from '@/components/ui/button';
import { useToast } from '@/hooks/use-toast';
import { MAX_DESC_LENGTH } from '@/lib/constants/eventSubmitFormContants';
import { EventFormValues } from '@/lib/schemas/eventSubmitFormSchema';

interface StepDetailsAndCategoryProps {
  control: Control<EventFormValues>;
  // watch: UseFormWatch<EventFormValues>;
  // setValue: UseFormSetValue<EventFormValues>;
  categories: { id: number; name: string }[];
}

type UploadStatus = 'uploading' | 'success' | 'error';

type UploadItem = {
  id: string;
  clientName: string;
  serverName?: string;
  status: UploadStatus;
  message?: string;
  previewUrl?: string;
};

export default function StepDetailsAndCategory({
  categories,
  control,
}: StepDetailsAndCategoryProps) {
  const t = useTranslations('eventSubmit.stepDetails');
  const { toast } = useToast();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [uploads, setUploads] = useState<UploadItem[]>([]);
  const cancelledIdsRef = useRef<Set<string>>(new Set());

  const {
    field: { value: imagesValue, onChange: setImages },
  } = useController({
    control,
    name: 'uploadedImages',
  });

  const maxFiles = 2;
  const remainingSlots = Math.max(0, maxFiles - uploads.length);

  const handlePickFiles = () => {
    fileInputRef.current?.click();
  };

  const handleFilesSelected = async (event: ChangeEvent<HTMLInputElement>) => {
    const fileList = Array.from(event.target.files ?? []);
    event.target.value = '';

    if (remainingSlots <= 0) {
      toast({
        variant: 'destructive',
        title: t('imagesLimitTitle'),
        description: t('imagesLimitReached'),
      });
      return;
    }

    const existingNames = new Set(uploads.map((item) => item.serverName ?? item.clientName));

    const filesToProcess = fileList
      .filter((file) => !existingNames.has(file.name))
      .slice(0, remainingSlots);

    if (fileList.length > remainingSlots) {
      toast({
        variant: 'destructive',
        title: t('imagesLimitTitle'),
        description: t('imagesLimitReached'),
      });
    }

    for (const file of filesToProcess) {
      const extension = file.name.split('.').pop()?.toLowerCase();
      if (!extension || !['jpg', 'jpeg'].includes(extension)) {
        toast({
          variant: 'destructive',
          title: t('imagesInvalidTypeTitle'),
          description: t('imagesInvalidType'),
        });
        continue;
      }
      if (file.size > 5 * 1024 * 1024) {
        toast({
          variant: 'destructive',
          title: t('imagesInvalidSizeTitle'),
          description: t('imagesInvalidSize'),
        });
        continue;
      }

      const uploadId = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
      const previewUrl = URL.createObjectURL(file);
      setUploads((prev) => [
        ...prev,
        {
          id: uploadId,
          clientName: file.name,
          status: 'uploading',
          previewUrl,
        },
      ]);

      try {
        const formData = new FormData();
        formData.append('file', file);

        const response = await fetch('/api/upload-event-image', {
          method: 'POST',
          body: formData,
        });

        const data = await response.json();
        if (!response.ok || !data?.success) {
          throw new Error(data?.message || t('imagesUploadError'));
        }

        const resolvedFileName =
          typeof data?.fileName === 'string' && data.fileName.trim().length > 0
            ? data.fileName
            : file.name;

        if (cancelledIdsRef.current.has(uploadId)) {
          return;
        }

        setUploads((prev) =>
          prev.map((item) =>
            item.id === uploadId
              ? {
                  ...item,
                  status: 'success',
                  serverName: resolvedFileName,
                }
              : item
          )
        );
      } catch (error) {
        if (cancelledIdsRef.current.has(uploadId)) {
          return;
        }
        setUploads((prev) =>
          prev.map((item) =>
            item.id === uploadId
              ? {
                  ...item,
                  status: 'error',
                  message: error instanceof Error ? error.message : t('imagesUploadError'),
                }
              : item
          )
        );
      }
    }
  };

  const handleRemoveUpload = async (upload: UploadItem) => {
    const fileName = upload.serverName ?? upload.clientName;
    const isUploaded = Boolean(upload.serverName);

    if (isUploaded) {
      const response = await fetch('/api/delete-event-image', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ fileName }),
      });

      if (!response.ok) {
        toast({
          variant: 'destructive',
          title: t('imagesDeleteErrorTitle'),
          description: t('imagesDeleteError'),
        });
        return;
      }
    }

    if (upload.status === 'uploading') {
      cancelledIdsRef.current.add(upload.id);
    }

    setUploads((prev) => prev.filter((item) => item.id !== upload.id));

    if (upload.previewUrl) {
      URL.revokeObjectURL(upload.previewUrl);
    }
  };

  useEffect(() => {
    const successful = uploads
      .filter((item) => item.status === 'success' && item.serverName)
      .map((item) => item.serverName as string);

    const current = (imagesValue ?? []) as string[];
    const isSame =
      current.length === successful.length &&
      current.every((value, index) => value === successful[index]);

    if (!isSame) {
      setImages(successful);
    }
  }, [uploads, imagesValue, setImages]);

  useEffect(() => {
    return () => {
      uploads.forEach((item) => {
        if (item.previewUrl) {
          URL.revokeObjectURL(item.previewUrl);
        }
      });
    };
  }, [uploads]);

  return (
    <div className="grid gap-6">
      <div className="bg-white/70 p-5 sm:p-6 space-y-6">
        <Field.Input
          control={control}
          name="eventName"
          label={t('eventTitle')}
          helper={t('eventSubtitle')}
          placeholder={t('eventTitlePlaceholder')}
          required
          maxLength={200}
        />

        <Field.Radio
          control={control}
          name="eventCategory"
          label={t('categoriesTitle')}
          helper={t('categoriesSubtitle')}
          required
          options={categories}
          customOptionId={111004} // Egyeb
          customFieldName="customRadioInput"
          customFieldPlaceholder={t('categoryOtherTitle')}
        />
      </div>

      <div className="bg-white/70 p-5 sm:p-6 space-y-6">
        <Field.Textarea
          control={control}
          name="description"
          label={t('descriptionTitle')}
          helper={t('descriptionSubtitle')}
          placeholder={t('descriptionPlaceholder')}
          maxLength={MAX_DESC_LENGTH}
          rows={5}
        />

        <Field.Textarea
          control={control}
          label={t('notesTitle')}
          helper={t('notesSubtitle')}
          name="notes"
          rows={6}
          placeholder={t('notesPlaceholder')}
          maxLength={1000}
        />
      </div>

      <div className="bg-white/70 p-5 sm:p-6">
        <Field.Wrapper label={t('linksTitle')}>
          <div className="grid gap-6 md:grid-cols-2">
            <Field.Input
              control={control}
              helper={t('infoUrlHelper')}
              name="infoUrl"
              type="url"
              placeholder={t('infoUrlPlaceholder')}
            />
            <Field.Input
              control={control}
              helper={t('ticketUrlHelper')}
              name="ticketUrl"
              type="url"
              placeholder={t('ticketUrlPlaceholder')}
            />
          </div>
        </Field.Wrapper>

        <div className="mt-6">
          <Field.Wrapper label={t('imagesTitle')} helper={t('imagesHelper')}>
            <input
              ref={fileInputRef}
              type="file"
              accept=".jpg,.jpeg,image/jpeg"
              multiple
              className="hidden"
              onChange={handleFilesSelected}
            />

            <div className="flex flex-wrap items-center gap-3">
              <Button
                type="button"
                variant="outline"
                onClick={handlePickFiles}
                disabled={remainingSlots <= 0}
                className="flex items-center gap-2"
              >
                <UploadCloud className="h-4 w-4" />
                {t('imagesButton')}
              </Button>
              <span className="text-xs uppercase tracking-[0.2em] text-[#151720]/50">
                {t('imagesLimit', { count: maxFiles })}
              </span>
            </div>

            <div className="mt-4 space-y-3">
              {uploads.length === 0 ? (
                <div className="text-sm text-[#151720]/50">{t('imagesEmpty')}</div>
              ) : null}

              {uploads.map((upload) => {
                const statusMessage =
                  upload.status === 'uploading'
                    ? t('imagesUploading')
                    : upload.status === 'error'
                      ? upload.message || t('imagesUploadError')
                      : t('imagesUploaded');
                const displayName = upload.serverName ?? upload.clientName;

                return (
                  <div
                    key={upload.id}
                    className="flex items-center justify-between gap-4 border-b border-[#151720]/10 pb-2"
                  >
                    <div className="flex items-center gap-3">
                      {upload.previewUrl ? (
                        <div className="h-12 w-12 border border-[#151720]/10 bg-white overflow-hidden">
                          <img
                            src={upload.previewUrl}
                            alt={displayName}
                            className="h-full w-full object-cover"
                          />
                        </div>
                      ) : (
                        <div className="h-12 w-12 border border-[#151720]/10 bg-white/60" />
                      )}
                      <div>
                        <div className="text-sm text-[#151720]">{displayName}</div>
                        <div className="text-xs text-[#151720]/60 flex items-center gap-2">
                          {upload.status === 'uploading' && (
                            <Loader2 className="h-3 w-3 animate-spin" />
                          )}
                          <span>{statusMessage}</span>
                        </div>
                      </div>
                    </div>
                    {upload.status !== 'uploading' && (
                      <button
                        type="button"
                        onClick={() => handleRemoveUpload(upload)}
                        className="text-xs uppercase tracking-[0.2em] text-[#151720]/60 hover:text-[#151720]"
                      >
                        <span className="inline-flex items-center gap-1">
                          <X className="h-3 w-3" />
                          {t('imagesRemove')}
                        </span>
                      </button>
                    )}
                  </div>
                );
              })}
            </div>
          </Field.Wrapper>
        </div>
      </div>
    </div>
  );
}
