import React from 'react';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import {
  useForm,
  UseFormProps,
  UseFormReturn,
  SubmitHandler,
  FieldErrors
} from 'react-hook-form';
import { Form } from 'react-compose-form';
import { InputControl } from '@/components/form/control/input.control';
import { TextareaControl } from '@/components/form/control/textarea.control';
import { FileControl } from '@/components/form/control/file.control';
import { SelectControl } from '@/components/form/control/select.control';
import {
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from '@/components/ui/select';
import {
  MediaScope,
  MediaScopeHelpers
} from '@/server/modules/media/types/media-scope.enum';

export const CreateMediaFormSchema = z.object({
  scope: z.nativeEnum(MediaScope),
  author: z.string(),
  alt: z.string(),
  caption: z.string(),
  file: z.instanceof(File, {
    message: 'File is missing'
  })
});

export const UpdateMediaFormSchema = CreateMediaFormSchema.omit({
  file: true
}).extend({
  file: z.instanceof(File).optional()
});

export type MediaFormValues =
  | z.infer<typeof CreateMediaFormSchema>
  | z.infer<typeof UpdateMediaFormSchema>;

export const useMediaForm = (
  mode: 'create' | 'update',
  props: Omit<UseFormProps<MediaFormValues>, 'resolver'> = {}
): UseFormReturn<MediaFormValues> => {
  return useForm<MediaFormValues>({
    ...props,
    resolver: zodResolver(
      mode === 'create' ? CreateMediaFormSchema : UpdateMediaFormSchema
    )
  });
};

type MediaFormProps = {
  id?: string;
  mode: 'create' | 'update';
  acceptedFileTypes?: string[];
  preview?: {
    alt?: string;
    mimeType?: string;
    url?: string;
  };
  control?: UseFormReturn<MediaFormValues>;
  onSubmit?: SubmitHandler<MediaFormValues>;
  onInvalid?: (errors: FieldErrors<MediaFormValues>) => void;
  hiddenExtraFields?: Partial<
    Record<keyof Omit<MediaFormValues, 'file'>, boolean>
  >;
};

export const MediaForm: React.FC<MediaFormProps> = (props) => {
  const {
    id,
    mode,
    acceptedFileTypes,
    control,
    preview,
    onSubmit,
    onInvalid,
    hiddenExtraFields = {}
  } = props;
  const isVisible = (field: keyof Omit<MediaFormValues, 'file'>) =>
    !hiddenExtraFields[field];

  const form = useMediaForm(mode, {
    formControl: control
  });

  return (
    <Form<MediaFormValues>
      id={id}
      formControl={form}
      onSubmit={onSubmit}
      onInvalid={onInvalid}
    >
      <div className='flex flex-col gap-4'>
        <FileControl
          label='Fil'
          acceptedFileTypes={acceptedFileTypes}
          preview={preview}
          name='file'
        />
        {isVisible('scope') && (
          <SelectControl label='Omfang' name='scope'>
            <SelectTrigger className='w-full'>
              <SelectValue placeholder='Vælg et omfang' />
            </SelectTrigger>
            <SelectContent>
              {Object.entries(MediaScope).map(([, scope]) => (
                <SelectItem key={scope} value={scope}>
                  {MediaScopeHelpers.getLabel(scope)}
                </SelectItem>
              ))}
            </SelectContent>
          </SelectControl>
        )}

        {isVisible('alt') && (
          <TextareaControl label='Alt' placeholder='alt' name='alt' />
        )}
        {isVisible('author') && (
          <InputControl
            label='Forfatter'
            placeholder='Forfatter'
            name='author'
          />
        )}
        {isVisible('caption') && (
          <TextareaControl
            label='Billedtekst'
            placeholder='Billedtekst'
            name='caption'
          />
        )}
      </div>
    </Form>
  );
};
