import { z } from "zod";
import { PropsWithChildren, useCallback, useEffect, useState } from "react";
import { useForm } from "@tanstack/react-form";
import { invoke } from "@tauri-apps/api/core";
import { CornerUpLeftIcon, Loader2Icon, SaveIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Field,
  FieldContent,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { Separator } from "@/components/ui/separator";
import { Slider } from "@/components/ui/slider";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import DragBar from "@/components/drag-bar";

const config = z.object({
  $schema: z.string(),
  locale: z.enum(["en", "pt"]),
  display: z.object({
    width: z.number().int().min(800),
    height: z.number().int().min(600),
    frequency: z.number().transform((value) => Math.ceil(value)),
    windowed: z.boolean(),
  }),
  gamma: z.union([
    z.literal(1),
    z.literal(2),
    z.literal(3),
    z.literal(4),
    z.literal(5),
  ]),

  volume: z.object({
    music: z.number().min(0).max(100),
    voice: z.number().min(0).max(100),
  }),

  show_mob: z.object({
    level: z.boolean(),
    ai_flag: z.boolean(),
  }),

  shadow_level: z.union([
    z.literal(0),
    z.literal(1),
    z.literal(2),
    z.literal(3),
  ]),
  fog_mode_on: z.boolean(),
  camera_mode: z.enum(["far", "close"]),
  field_of_view: z.number().min(0).max(100),
  private_shop: z.object({
    view_distance: z.number().min(0).max(100),
    show_sales_text: z.boolean(),
  }),
});

type Config = z.infer<typeof config>;

type Resolution = { width: number; height: number; frequency: number };

const Category = ({
  id,
  title,
  subtitle,
  children,
}: PropsWithChildren<{ title: string; subtitle: string; id: string }>) => {
  return (
    <AccordionItem
      value={id}
      className="bg-linear-to-tr from-primary/5 to-primary/0 py-1"
    >
      <AccordionTrigger className="hover:no-underline! px-6 py-4 rounded-none! items-center">
        <div>
          <FieldLegend>{title}</FieldLegend>
          <FieldDescription>{subtitle}</FieldDescription>
        </div>
      </AccordionTrigger>
      <AccordionContent className="flex flex-col gap-2.5 px-6">
        <FieldSet className="pt-2">{children}</FieldSet>
      </AccordionContent>
    </AccordionItem>
  );
};

const Settings = ({
  resolutions,
  initialConfig,
}: {
  resolutions: Resolution[];
  initialConfig: Config;
}) => {
  const [useCustomResolution, setUseCustomResolution] = useState(
    resolutions.findIndex(
      (res) =>
        res.height === initialConfig.display.height &&
        res.width === initialConfig.display.width &&
        Math.ceil(res.frequency) === initialConfig.display.frequency
    ) === -1
  );

  const form = useForm({
    defaultValues: initialConfig,
    validators: {
      onSubmit: config,
    },
    onSubmit: async ({ value }) => {
      await invoke<boolean>("set_config", { config: value });
    },
  });

  const setPredefinedResolution = useCallback(
    (index: string) => {
      const { height, width, frequency } = resolutions[Number(index)];
      form.setFieldValue("display.height", height);
      form.setFieldValue("display.width", width);
      form.setFieldValue("display.frequency", Math.ceil(frequency));
    },
    [resolutions, form.setFieldValue]
  );

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        form.handleSubmit();
      }}
      className="flex flex-col h-screen"
    >
      <Accordion
        type="single"
        collapsible
        defaultValue="general"
        className="divide-primary/10 divide-y"
      >
        <Category id="general" title="General" subtitle="Basic settings">
          <form.Field
            name="locale"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Language</FieldLabel>
                    <Select
                      name={field.name}
                      value={field.state.value}
                      onValueChange={(e) =>
                        field.handleChange(e as Config["locale"])
                      }
                      aria-invalid={isInvalid}
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue placeholder="Choose language" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="en">English</SelectItem>
                        <SelectItem value="pt">Portuguese</SelectItem>
                      </SelectContent>
                    </Select>
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="show_mob.ai_flag"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <FieldSet>
                  <FieldGroup data-slot="checkbox-group">
                    <Field orientation="horizontal" data-invalid={isInvalid}>
                      <Checkbox
                        id={field.name}
                        name={field.name}
                        checked={field.state.value}
                        onCheckedChange={(checked) =>
                          field.handleChange(checked === true)
                        }
                      />
                      <FieldLabel htmlFor={field.name} className="font-normal">
                        Show mob agressive (
                        <span className="text-destructive">*</span>)
                      </FieldLabel>
                    </Field>
                  </FieldGroup>
                  {isInvalid && <FieldError errors={field.state.meta.errors} />}
                </FieldSet>
              );
            }}
          />
          <form.Field
            name="show_mob.level"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <FieldSet>
                  <FieldGroup data-slot="checkbox-group">
                    <Field orientation="horizontal" data-invalid={isInvalid}>
                      <Checkbox
                        id={field.name}
                        name={field.name}
                        checked={field.state.value}
                        onCheckedChange={(checked) =>
                          field.handleChange(checked === true)
                        }
                      />
                      <FieldLabel htmlFor={field.name} className="font-normal">
                        Show mob level
                      </FieldLabel>
                    </Field>
                  </FieldGroup>
                  {isInvalid && <FieldError errors={field.state.meta.errors} />}
                </FieldSet>
              );
            }}
          />
        </Category>
        <Category id="display" title="Display" subtitle="Screen settings">
          <div className="flex items-center gap-3">
            <Checkbox
              id="set-predefined-resolution"
              checked={useCustomResolution}
              onCheckedChange={(v) => setUseCustomResolution(!!v)}
            />
            <Label htmlFor="set-predefined-resolution">
              Use custom resolution
            </Label>
          </div>
          <div className="grid grid-flow-col-dense gap-x-4">
            {!useCustomResolution ? (
              <FieldContent>
                <FieldLabel htmlFor="predefined-resolution">
                  Resolution
                </FieldLabel>
                <Select onValueChange={setPredefinedResolution}>
                  <SelectTrigger id="predefined-resolution" className="w-full">
                    <SelectValue placeholder="Choose resolution" />
                  </SelectTrigger>
                  <SelectContent>
                    {resolutions.map((resolution, index) => (
                      <SelectItem value={index.toString()}>
                        {resolution.width}x{resolution.height}{" "}
                        {resolution.frequency}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </FieldContent>
            ) : (
              <>
                <form.Field
                  name="display.width"
                  children={(field) => {
                    const isInvalid =
                      field.state.meta.isTouched && !field.state.meta.isValid;

                    return (
                      <Field data-invalid={isInvalid}>
                        <FieldContent>
                          <FieldLabel htmlFor={field.name}>Width</FieldLabel>
                          <Input
                            id={field.name}
                            name={field.name}
                            value={field.state.value}
                            onBlur={field.handleBlur}
                            onChange={(e) =>
                              field.handleChange(Number(e.target.value))
                            }
                            aria-invalid={isInvalid}
                            placeholder="Width"
                          />
                          {isInvalid && (
                            <FieldError errors={field.state.meta.errors} />
                          )}
                        </FieldContent>
                      </Field>
                    );
                  }}
                />
                <form.Field
                  name="display.height"
                  children={(field) => {
                    const isInvalid =
                      field.state.meta.isTouched && !field.state.meta.isValid;

                    return (
                      <Field data-invalid={isInvalid}>
                        <FieldContent>
                          <FieldLabel htmlFor={field.name}>Height</FieldLabel>
                          <Input
                            id={field.name}
                            name={field.name}
                            value={field.state.value}
                            onBlur={field.handleBlur}
                            onChange={(e) =>
                              field.handleChange(Number(e.target.value))
                            }
                            aria-invalid={isInvalid}
                            placeholder="Height"
                          />
                          {isInvalid && (
                            <FieldError errors={field.state.meta.errors} />
                          )}
                        </FieldContent>
                      </Field>
                    );
                  }}
                />
                <form.Field
                  name="display.frequency"
                  children={(field) => {
                    const isInvalid =
                      field.state.meta.isTouched && !field.state.meta.isValid;

                    return (
                      <Field data-invalid={isInvalid}>
                        <FieldContent>
                          <FieldLabel htmlFor={field.name}>
                            Frequency
                          </FieldLabel>
                          <Select
                            name={field.name}
                            value={field.state.value.toString()}
                            onValueChange={(e) => field.handleChange(Number(e))}
                            aria-invalid={isInvalid}
                          >
                            <SelectTrigger className="w-full">
                              <SelectValue placeholder="Choose frequency" />
                            </SelectTrigger>
                            <SelectContent>
                              <SelectItem value="30">30</SelectItem>
                              <SelectItem value="60">60</SelectItem>
                              <SelectItem value="120">120</SelectItem>
                              <SelectItem value="144">144</SelectItem>
                            </SelectContent>
                          </Select>
                          {isInvalid && (
                            <FieldError errors={field.state.meta.errors} />
                          )}
                        </FieldContent>
                      </Field>
                    );
                  }}
                />
              </>
            )}
          </div>
          <form.Field
            name="gamma"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Gamma</FieldLabel>
                    <Select
                      name={field.name}
                      value={field.state.value.toString()}
                      onValueChange={(e) =>
                        field.handleChange(Number(e) as Config["gamma"])
                      }
                      aria-invalid={isInvalid}
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue placeholder="Set gamma" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="1">Level 1</SelectItem>
                        <SelectItem value="2">Level 2</SelectItem>
                        <SelectItem value="3">Level 3</SelectItem>
                        <SelectItem value="4">Level 4</SelectItem>
                        <SelectItem value="5">Level 5</SelectItem>
                      </SelectContent>
                    </Select>
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="display.windowed"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <FieldSet>
                  <FieldGroup data-slot="checkbox-group">
                    <Field orientation="horizontal" data-invalid={isInvalid}>
                      <Checkbox
                        id="form-tanstack-checkbox-responses"
                        name={field.name}
                        checked={field.state.value}
                        onCheckedChange={(checked) =>
                          field.handleChange(checked === true)
                        }
                      />
                      <FieldLabel
                        htmlFor="form-tanstack-checkbox-responses"
                        className="font-normal"
                      >
                        Windowed
                      </FieldLabel>
                    </Field>
                  </FieldGroup>
                  {isInvalid && <FieldError errors={field.state.meta.errors} />}
                </FieldSet>
              );
            }}
          />
        </Category>
        <Category id="sound" title="Sound" subtitle="Volume settings">
          <FieldLegend>Sound</FieldLegend>
          <FieldDescription>Volume settings</FieldDescription>
          <form.Field
            name="volume.music"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Music</FieldLabel>
                    <Slider
                      className="mt-2"
                      id={field.name}
                      name={field.name}
                      value={[Number(field.state.value)]}
                      onValueChange={(v) => field.handleChange(v[0])}
                      max={100}
                      step={1}
                      aria-invalid={isInvalid}
                    />
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="volume.voice"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid} className="mb-3">
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Sound Effects</FieldLabel>
                    <Slider
                      className="mt-2"
                      id={field.name}
                      name={field.name}
                      value={[Number(field.state.value)]}
                      onValueChange={(v) => field.handleChange(v[0])}
                      max={100}
                      step={1}
                      aria-invalid={isInvalid}
                    />
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
        </Category>
        <Category
          id="graphics"
          title="Graphics"
          subtitle="Quality and Performance settings"
        >
          <form.Field
            name="shadow_level"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Shadows</FieldLabel>
                    <Select
                      name={field.name}
                      value={field.state.value?.toString()}
                      onValueChange={(e) =>
                        field.handleChange(Number(e) as Config["shadow_level"])
                      }
                      aria-invalid={isInvalid}
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue placeholder="Set shadows" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="0">None</SelectItem>
                        <SelectItem value="1">Background</SelectItem>
                        <SelectItem value="2">Background + Player</SelectItem>
                        <SelectItem value="3">All</SelectItem>
                      </SelectContent>
                    </Select>
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="fog_mode_on"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <Label className="hover:bg-accent/50 flex items-start gap-3 rounded-lg border p-3 has-aria-checked:border-blue-600 has-aria-checked:bg-blue-50 dark:has-aria-checked:border-blue-900 dark:has-aria-checked:bg-blue-950">
                      <Checkbox
                        id="toggle-2"
                        checked={field.state.value}
                        onCheckedChange={(checked) =>
                          field.handleChange(checked === true)
                        }
                        className="data-[state=checked]:border-blue-600 data-[state=checked]:bg-blue-600 data-[state=checked]:text-white dark:data-[state=checked]:border-blue-700 dark:data-[state=checked]:bg-blue-700"
                      />
                      <div className="grid gap-1.5 font-normal">
                        <p className="text-sm leading-none font-medium">Fog</p>
                        <p className="text-muted-foreground text-sm">
                          Keep enabled if you have a very low spec computer.
                        </p>
                      </div>
                    </Label>
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="camera_mode"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Camera Mode</FieldLabel>
                    <Select
                      name={field.name}
                      value={field.state.value}
                      onValueChange={(e) =>
                        field.handleChange(e as Config["camera_mode"])
                      }
                      aria-invalid={isInvalid}
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue placeholder="Choose camera mode" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="close">Close</SelectItem>
                        <SelectItem value="far">Far</SelectItem>
                      </SelectContent>
                    </Select>
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="field_of_view"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>Field of View</FieldLabel>
                    <Slider
                      className="mt-2"
                      id={field.name}
                      name={field.name}
                      value={[Number(field.state.value)]}
                      onValueChange={(v) => field.handleChange(v[0])}
                      max={100}
                      step={1}
                      aria-invalid={isInvalid}
                    />
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="private_shop.show_sales_text"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <Label className="hover:bg-accent/50 flex items-start gap-3 rounded-lg border p-3 has-aria-checked:border-blue-600 has-aria-checked:bg-blue-50 dark:has-aria-checked:border-blue-900 dark:has-aria-checked:bg-blue-950">
                      <Checkbox
                        id="toggle-2"
                        checked={field.state.value}
                        onCheckedChange={(checked) =>
                          field.handleChange(checked === true)
                        }
                        className="data-[state=checked]:border-blue-600 data-[state=checked]:bg-blue-600 data-[state=checked]:text-white dark:data-[state=checked]:border-blue-700 dark:data-[state=checked]:bg-blue-700"
                      />
                      <div className="grid gap-1.5 font-normal">
                        <p className="text-sm leading-none font-medium">
                          Show Sales Text
                        </p>
                        <p className="text-muted-foreground text-sm">
                          Disable in low spec computers for performance.
                        </p>
                      </div>
                    </Label>
                  </FieldContent>
                </Field>
              );
            }}
          />
          <form.Field
            name="private_shop.view_distance"
            children={(field) => {
              const isInvalid =
                field.state.meta.isTouched && !field.state.meta.isValid;

              return (
                <Field data-invalid={isInvalid}>
                  <FieldContent>
                    <FieldLabel htmlFor={field.name}>
                      Shop View Distance
                    </FieldLabel>
                    <Slider
                      className="mt-2"
                      id={field.name}
                      name={field.name}
                      value={[Number(field.state.value)]}
                      onValueChange={(v) => field.handleChange(v[0])}
                      max={100}
                      step={1}
                      aria-invalid={isInvalid}
                    />
                    <FieldDescription>
                      Keep low on low spec computers.
                    </FieldDescription>
                    {isInvalid && (
                      <FieldError errors={field.state.meta.errors} />
                    )}
                  </FieldContent>
                </Field>
              );
            }}
          />
        </Category>
      </Accordion>
      <Separator />
      <section className="px-6 py-5 mt-auto">
        <div className="grid grid-cols-2 gap-x-4">
          <form.Subscribe
            selector={(state) => [state.canSubmit, state.isSubmitting]}
            children={([canSubmit, isSubmitting]) => (
              <Button type="submit" disabled={!canSubmit}>
                {isSubmitting ? (
                  <Loader2Icon className="animate-spin" />
                ) : (
                  <SaveIcon />
                )}
                Save
              </Button>
            )}
          />
          <Button type="button" variant="outline" onClick={() => form.reset()}>
            <CornerUpLeftIcon />
            Reset
          </Button>
        </div>
      </section>
    </form>
  );
};

function App() {
  const [resolutions, setResolutions] = useState<Resolution[]>([]);
  const [config, setConfig] = useState<Config | null>(null);

  const loadResolutions = useCallback(async () => {
    const baseResolutions = await invoke<Resolution[]>("get_resolutions");
    const baseConfig = await invoke<Config>("get_config");

    setResolutions(baseResolutions);
    setConfig(baseConfig);
  }, []);

  useEffect(() => {
    loadResolutions();
  }, []);

  return (
    <main>
      <DragBar />
      {config ? (
        <Settings resolutions={resolutions} initialConfig={config} />
      ) : (
        <div>Loading</div>
      )}
    </main>
  );
}

export default App;
