import {
  Button,
  InputCheckbox,
  InputCheckboxList,
  InputSelect,
  InputSlider,
  InputTextarea,
} from "@theme";
import { formatBytes } from "@utils/format.ts";
import { MODELS } from "@utils/models.ts";
import { TOOLS } from "@utils/tools.ts";
import { useEffect, useRef } from "react";
import { Controller, useForm } from "react-hook-form";

import type { ChatSettings } from "./types.ts";

export default function ChatSettingsModalForm({
  defaultValues,
  onSubmit,
  downloadedModels,
  visible,
}: {
  defaultValues: ChatSettings;
  onSubmit: (data: ChatSettings) => void;
  downloadedModels: Array<string>;
  visible: boolean;
}) {
  const selectModelRef = useRef<HTMLSelectElement>(null);
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm<ChatSettings>({
    defaultValues,
  });

  const modelOptions = Object.values(
    Object.entries(MODELS).reduce(
      (groups, [key, model]) => {
        const groupName = model.group;

        if (!groups[groupName]) {
          groups[groupName] = {
            label: groupName.charAt(0).toUpperCase() + groupName.slice(1),
            options: [],
          };
        }

        groups[groupName].options.push({
          value: key,
          label: `${model.title} - ${formatBytes(model.size)}${downloadedModels.includes(key) ? " *" : ""}`,
          title: model.title,
        });

        return groups;
      },
      {} as Record<
        string,
        {
          label: string;
          options: Array<{ value: string; label: string; title: string }>;
        }
      >
    )
  )
    .sort((a, b) => a.label.localeCompare(b.label))
    .map((group) => ({
      ...group,
      options: group.options
        .sort((a, b) => a.title.localeCompare(b.title))
        .map(({ value, label }) => ({ value, label })),
    }));

  const toolOptions = TOOLS.map((tool) => ({
    name: tool.name,
    label: tool.name,
    description: tool.description,
  }));

  useEffect(() => {
    if (visible && selectModelRef.current) {
      // Use setTimeout to ensure the element is rendered and ready for focus
      setTimeout(() => {
        selectModelRef.current?.focus();
      }, 200);
    }
  }, [visible]);

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-6">
      <Controller
        name="modelKey"
        control={control}
        rules={{ required: "Model is required" }}
        render={({ field }) => (
          <InputSelect
            id="model-select"
            label="Model"
            error={errors.modelKey?.message as string}
            value={field.value}
            onChange={field.onChange}
            options={modelOptions}
            required
            tooltip="(*) are already downloaded"
            ref={selectModelRef}
          />
        )}
      />

      <Controller
        name="systemPrompt"
        control={control}
        rules={{ required: "System prompt is required" }}
        render={({ field }) => (
          <InputTextarea
            id="system-prompt"
            label="System Prompt"
            placeholder="You are a helpful AI Assistant"
            error={errors.systemPrompt?.message as string}
            value={field.value}
            onChange={field.onChange}
            rows={6}
            required
          />
        )}
      />

      <Controller
        name="tools"
        control={control}
        render={({ field }) => (
          <InputCheckboxList
            id="tools"
            label="Tools (only if supported by the model)"
            options={toolOptions}
            value={field.value}
            onChange={field.onChange}
            error={errors.tools?.message as string}
          />
        )}
      />

      <Controller
        name="temperature"
        control={control}
        rules={{
          required: "Temperature is required",
          min: { value: 0, message: "Temperature must be at least 0" },
          max: { value: 2, message: "Temperature must be at most 2" },
        }}
        render={({ field }) => (
          <InputSlider
            id="temperature"
            label="Temperature"
            value={field.value}
            onChange={field.onChange}
            min={0}
            max={2}
            step={0.1}
            error={errors.temperature?.message as string}
            tooltip="Controls randomness in responses. Lower values are more focused, higher values are more creative."
          />
        )}
      />

      <Controller
        name="enableThinking"
        control={control}
        render={({ field }) => (
          <InputCheckbox
            id="enable-thinking"
            label="Enable Thinking"
            description="Allow the model to show its reasoning process (only if supported by the model)"
            checked={field.value}
            onChange={field.onChange}
            error={errors.enableThinking?.message as string}
          />
        )}
      />

      <Button type="submit">Start Conversation</Button>
    </form>
  );
}
