"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@workspace/ui/components/button";
import { Card, CardContent } from "@workspace/ui/components/card";
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@workspace/ui/components/form";
import { ScrollArea } from "@workspace/ui/components/scroll-area";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@workspace/ui/components/select";
import {
  Sheet,
  SheetContent,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@workspace/ui/components/sheet";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@workspace/ui/components/tabs";
import { Textarea } from "@workspace/ui/components/textarea";
import { ArrayInput } from "@workspace/ui/composed/dynamic-Inputs";
import { EnhancedInput } from "@workspace/ui/composed/enhanced-input";
import { Icon } from "@workspace/ui/composed/icon";
import {
  getNodeConfig,
  updateNodeConfig,
} from "@workspace/ui/services/admin/system";
import { unitConversion } from "@workspace/ui/utils/unit-conversions";
import { DicesIcon } from "lucide-react";
import { uid } from "radash";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { z } from "zod";
import { SS_CIPHERS } from "./form-schema";

const dnsConfigSchema = z.object({
  proto: z.string(), // z.enum(['tcp', 'udp', 'tls', 'https', 'quic']),
  address: z.string(),
  domains: z.array(z.string()),
});

const outboundConfigSchema = z.object({
  name: z.string(),
  protocol: z.string(),
  address: z.string(),
  port: z.number(),
  cipher: z.string().optional(),
  password: z.string().optional(),
  rules: z.array(z.string()).optional(),
});

const nodeConfigSchema = z.object({
  node_secret: z.string().optional(),
  node_pull_interval: z.number().optional(),
  node_push_interval: z.number().optional(),
  traffic_report_threshold: z.number().optional(),
  ip_strategy: z.enum(["prefer_ipv4", "prefer_ipv6"]).optional(),
  dns: z.array(dnsConfigSchema).optional(),
  block: z.array(z.string()).optional(),
  outbound: z.array(outboundConfigSchema).optional(),
});
type NodeConfigFormData = z.infer<typeof nodeConfigSchema>;

export default function ServerConfig() {
  const { t } = useTranslation("servers");
  const [open, setOpen] = useState(false);
  const [saving, setSaving] = useState(false);

  const { data: cfgResp, refetch: refetchCfg } = useQuery({
    queryKey: ["getNodeConfig"],
    queryFn: async () => {
      const { data } = await getNodeConfig();
      return data.data as API.NodeConfig | undefined;
    },
    enabled: open,
  });

  const form = useForm<NodeConfigFormData>({
    resolver: zodResolver(nodeConfigSchema),
    defaultValues: {
      node_secret: "",
      node_pull_interval: undefined,
      node_push_interval: undefined,
      traffic_report_threshold: undefined,
      ip_strategy: "prefer_ipv4",
      dns: [],
      block: [],
      outbound: [],
    },
  });

  useEffect(() => {
    if (cfgResp) {
      form.reset({
        node_secret: cfgResp.node_secret ?? "",
        node_pull_interval: cfgResp.node_pull_interval as number | undefined,
        node_push_interval: cfgResp.node_push_interval as number | undefined,
        traffic_report_threshold: cfgResp.traffic_report_threshold as
          | number
          | undefined,
        ip_strategy:
          (cfgResp.ip_strategy as "prefer_ipv4" | "prefer_ipv6" | undefined) ||
          "prefer_ipv4",
        dns: cfgResp.dns || [],
        block: cfgResp.block || [],
        outbound: cfgResp.outbound || [],
      });
    }
  }, [cfgResp, form]);

  async function onSubmit(values: NodeConfigFormData) {
    setSaving(true);
    try {
      await updateNodeConfig(values as API.NodeConfig);
      toast.success(t("server_config.saveSuccess", "Saved successfully"));
      await refetchCfg();
      setOpen(false);
    } finally {
      setSaving(false);
    }
  }

  return (
    <Sheet onOpenChange={setOpen} open={open}>
      <SheetTrigger asChild>
        <Card>
          <CardContent>
            <div className="flex cursor-pointer items-center justify-between">
              <div className="flex items-center gap-3">
                <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
                  <Icon
                    className="h-5 w-5 text-primary"
                    icon="mdi:resistor-nodes"
                  />
                </div>
                <div className="flex-1">
                  <p className="font-medium">
                    {t("server_config.title", "Node configuration")}
                  </p>
                  <p className="truncate text-muted-foreground text-sm">
                    {t(
                      "server_config.description",
                      "Manage node communication keys, pull/push intervals."
                    )}
                  </p>
                </div>
              </div>
              <Icon className="size-6" icon="mdi:chevron-right" />
            </div>
          </CardContent>
        </Card>
      </SheetTrigger>

      <SheetContent className="w-[720px] max-w-full md:max-w-3xl">
        <SheetHeader>
          <SheetTitle>
            {t("server_config.title", "Node configuration")}
          </SheetTitle>
        </SheetHeader>

        <ScrollArea className="h-[calc(100dvh-48px-36px-36px-env(safe-area-inset-top))] px-6">
          <Tabs className="pt-4" defaultValue="basic">
            <TabsList className="grid w-full grid-cols-4">
              <TabsTrigger value="basic">
                {t("server_config.tabs.basic", "Basic Configuration")}
              </TabsTrigger>
              <TabsTrigger value="dns">
                {t("server_config.tabs.dns", "DNS Configuration")}
              </TabsTrigger>
              <TabsTrigger value="outbound">
                {t("server_config.tabs.outbound", "Outbound Rules")}
              </TabsTrigger>
              <TabsTrigger value="block">
                {t("server_config.tabs.block", "Block Rules")}
              </TabsTrigger>
            </TabsList>

            <Form {...form}>
              <form
                className="mt-4"
                id="server-config-form"
                onSubmit={form.handleSubmit(onSubmit)}
              >
                <TabsContent className="space-y-4" value="basic">
                  <FormField
                    control={form.control}
                    name="node_secret"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t(
                            "server_config.fields.communication_key",
                            "Communication key"
                          )}
                        </FormLabel>
                        <FormControl>
                          <EnhancedInput
                            onValueChange={field.onChange}
                            placeholder={t(
                              "server_config.fields.communication_key_placeholder",
                              "Please enter"
                            )}
                            suffix={
                              <div className="flex h-9 items-center bg-muted px-3">
                                <DicesIcon
                                  className="cursor-pointer"
                                  onClick={() => {
                                    const id = uid(32).toLowerCase();
                                    const formatted = `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(16, 20)}-${id.slice(20)}`;
                                    form.setValue("node_secret", formatted);
                                  }}
                                />
                              </div>
                            }
                            value={field.value || ""}
                          />
                        </FormControl>
                        <FormDescription>
                          {t(
                            "server_config.fields.communication_key_desc",
                            "Used for node authentication."
                          )}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    )}
                  />

                  <FormField
                    control={form.control}
                    name="node_pull_interval"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t(
                            "server_config.fields.node_pull_interval",
                            "Node pull interval"
                          )}
                        </FormLabel>
                        <FormControl>
                          <EnhancedInput
                            min={0}
                            onValueChange={field.onChange}
                            placeholder={t(
                              "server_config.fields.communication_key_placeholder",
                              "Please enter"
                            )}
                            suffix="S"
                            type="number"
                            value={field.value as number | undefined}
                          />
                        </FormControl>
                        <FormDescription>
                          {t(
                            "server_config.fields.node_pull_interval_desc",
                            "How often the node pulls configuration (seconds)."
                          )}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    )}
                  />

                  <FormField
                    control={form.control}
                    name="node_push_interval"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t(
                            "server_config.fields.node_push_interval",
                            "Node push interval"
                          )}
                        </FormLabel>
                        <FormControl>
                          <EnhancedInput
                            min={0}
                            onValueChange={field.onChange}
                            placeholder={t(
                              "server_config.fields.communication_key_placeholder",
                              "Please enter"
                            )}
                            step={0.1}
                            suffix="S"
                            type="number"
                            value={field.value as number | undefined}
                          />
                        </FormControl>
                        <FormDescription>
                          {t(
                            "server_config.fields.node_push_interval_desc",
                            "How often the node pushes stats (seconds)."
                          )}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    )}
                  />

                  <FormField
                    control={form.control}
                    name="traffic_report_threshold"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t(
                            "server_config.fields.traffic_report_threshold",
                            "Traffic Report Threshold"
                          )}
                        </FormLabel>
                        <FormControl>
                          <EnhancedInput
                            min={0}
                            onValueChange={(value) => {
                              field.onChange(unitConversion("mbToBits", value));
                            }}
                            placeholder="1"
                            suffix="MB"
                            type="number"
                            value={unitConversion(
                              "bitsToMb",
                              field.value as number | undefined
                            )}
                          />
                        </FormControl>
                        <FormDescription>
                          {t(
                            "server_config.fields.traffic_report_threshold_desc",
                            "Set the minimum threshold for traffic reporting."
                          )}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </TabsContent>

                <TabsContent className="space-y-4" value="dns">
                  <FormField
                    control={form.control}
                    name="ip_strategy"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t("server_config.fields.ip_strategy", "IP Strategy")}
                        </FormLabel>
                        <Select
                          onValueChange={field.onChange}
                          value={field.value}
                        >
                          <FormControl>
                            <SelectTrigger>
                              <SelectValue
                                placeholder={t(
                                  "server_config.fields.ip_strategy_placeholder",
                                  "Select IP strategy"
                                )}
                              />
                            </SelectTrigger>
                          </FormControl>
                          <SelectContent>
                            <SelectItem value="prefer_ipv4">
                              {t(
                                "server_config.fields.ip_strategy_ipv4",
                                "Prefer IPv4"
                              )}
                            </SelectItem>
                            <SelectItem value="prefer_ipv6">
                              {t(
                                "server_config.fields.ip_strategy_ipv6",
                                "Prefer IPv6"
                              )}
                            </SelectItem>
                          </SelectContent>
                        </Select>
                        <FormDescription>
                          {t(
                            "server_config.fields.ip_strategy_desc",
                            "Choose IP version preference for network connections"
                          )}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    )}
                  />

                  <FormField
                    control={form.control}
                    name="dns"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>
                          {t(
                            "server_config.fields.dns_config",
                            "DNS Configuration"
                          )}
                        </FormLabel>
                        <FormControl>
                          <ArrayInput
                            className="grid grid-cols-2 gap-2"
                            fields={[
                              {
                                name: "proto",
                                type: "select",
                                placeholder: t(
                                  "server_config.fields.dns_proto_placeholder",
                                  "Select type"
                                ),
                                options: [
                                  { label: "TCP", value: "tcp" },
                                  { label: "UDP", value: "udp" },
                                  { label: "TLS", value: "tls" },
                                  { label: "HTTPS", value: "https" },
                                  { label: "QUIC", value: "quic" },
                                ],
                              },
                              {
                                name: "address",
                                type: "text",
                                placeholder: "8.8.8.8:53",
                              },
                              {
                                name: "domains",
                                type: "textarea",
                                className: "col-span-2",
                                placeholder: t(
                                  "server_config.fields.dns_domains_placeholder",
                                  "One domain rule per line"
                                ),
                              },
                            ]}
                            onChange={(values) => {
                              const converted = values.map((item: any) => ({
                                proto: item.proto,
                                address: item.address,
                                domains:
                                  typeof item.domains === "string"
                                    ? item.domains
                                        .split("\n")
                                        .map((d: string) => d.trim())
                                    : item.domains || [],
                              }));
                              field.onChange(converted);
                            }}
                            value={(field.value || []).map((item) => ({
                              ...item,
                              domains: Array.isArray(item.domains)
                                ? item.domains.join("\n")
                                : "",
                            }))}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </TabsContent>

                <TabsContent className="space-y-4" value="outbound">
                  <FormField
                    control={form.control}
                    name="outbound"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <ArrayInput
                            className="grid grid-cols-2 gap-2"
                            fields={[
                              {
                                name: "name",
                                type: "text",
                                className: "col-span-2",
                                placeholder: t(
                                  "server_config.fields.outbound_name_placeholder",
                                  "Configuration name"
                                ),
                              },
                              {
                                name: "protocol",
                                type: "select",
                                placeholder: t(
                                  "server_config.fields.outbound_protocol_placeholder",
                                  "Select protocol"
                                ),
                                options: [
                                  { label: "HTTP", value: "http" },
                                  { label: "SOCKS", value: "socks" },
                                  {
                                    label: "Shadowsocks",
                                    value: "shadowsocks",
                                  },
                                  { label: "Brook", value: "brook" },
                                  { label: "Snell", value: "snell" },
                                  { label: "VMess", value: "vmess" },
                                  { label: "VLESS", value: "vless" },
                                  { label: "Trojan", value: "trojan" },
                                  { label: "WireGuard", value: "wireguard" },
                                  { label: "Hysteria", value: "hysteria" },
                                  { label: "TUIC", value: "tuic" },
                                  { label: "AnyTLS", value: "anytls" },
                                  { label: "Naive", value: "naive" },
                                  { label: "Direct", value: "direct" },
                                  { label: "Reject", value: "reject" },
                                ],
                              },
                              {
                                name: "cipher",
                                type: "select",
                                options: SS_CIPHERS.map((cipher) => ({
                                  label: cipher,
                                  value: cipher,
                                })),
                                visible: (item: Record<string, unknown>) =>
                                  item.protocol === "shadowsocks",
                              },
                              {
                                name: "address",
                                type: "text",
                                placeholder: t(
                                  "server_config.fields.outbound_address_placeholder",
                                  "Server address"
                                ),
                              },
                              {
                                name: "port",
                                type: "number",
                                placeholder: t(
                                  "server_config.fields.outbound_port_placeholder",
                                  "Port number"
                                ),
                              },
                              {
                                name: "password",
                                type: "text",
                                placeholder: t(
                                  "server_config.fields.outbound_password_placeholder",
                                  "Password (optional)"
                                ),
                              },
                              {
                                name: "rules",
                                type: "textarea",
                                className: "col-span-2",
                                placeholder: t(
                                  "server_config.fields.outbound_rules_placeholder",
                                  "One rule per line"
                                ),
                              },
                            ]}
                            onChange={(values) => {
                              const converted = values.map((item: any) => ({
                                name: item.name,
                                protocol: item.protocol,
                                address: item.address,
                                port: item.port,
                                cipher: item.cipher,
                                password: item.password,
                                rules:
                                  typeof item.rules === "string"
                                    ? item.rules
                                        .split("\n")
                                        .map((r: string) => r.trim())
                                    : item.rules || [],
                              }));
                              field.onChange(converted);
                            }}
                            value={(field.value || []).map((item) => ({
                              ...item,
                              rules: Array.isArray(item.rules)
                                ? item.rules.join("\n")
                                : "",
                            }))}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </TabsContent>

                <TabsContent className="space-y-4" value="block">
                  <FormField
                    control={form.control}
                    name="block"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <Textarea
                            onChange={(e) => {
                              const lines = e.target.value
                                .split("\n")
                                .map((line) => line.trim());
                              field.onChange(lines);
                            }}
                            placeholder={t(
                              "server_config.fields.block_rules_placeholder",
                              "One domain rule per line"
                            )}
                            rows={10}
                            value={(field.value || []).join("\n")}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </TabsContent>
              </form>
            </Form>
          </Tabs>
        </ScrollArea>

        <SheetFooter className="flex-row justify-end gap-2 pt-3">
          <Button
            disabled={saving}
            onClick={() => setOpen(false)}
            variant="outline"
          >
            {t("actions.cancel", "Cancel")}
          </Button>
          <Button disabled={saving} form="server-config-form" type="submit">
            <Icon
              className={saving ? "mr-2 animate-spin" : "hidden"}
              icon="mdi:loading"
            />
            {t("actions.save", "Save")}
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}
