import { zodResolver } from "@hookform/resolvers/zod";
import {
  Alert,
  AlertDescription,
  AlertTitle,
} from "@workspace/ui/components/alert";
import { Button } from "@workspace/ui/components/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@workspace/ui/components/form";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@workspace/ui/components/select";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@workspace/ui/components/tabs";
import { Textarea } from "@workspace/ui/components/textarea";
import { EnhancedInput } from "@workspace/ui/composed/enhanced-input";
import { updateLotteryActivityRules } from "@workspace/ui/services/admin/lottery";
import { PlusIcon, Trash2Icon, TriangleAlertIcon } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { useFieldArray, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
  buildCapsErrorMessage,
  buildEligibility,
  CHANCE_SOURCE_OPTIONS,
  CONDITION_PARAM_FIELDS,
  CONDITION_TYPES,
  getRuleEditorSchema,
  isEmptyEligibility,
  type RuleEditorValues,
  resolveEligibility,
  toRuleEditorValues,
  treeToSimple,
  validateJsonTree,
} from "./rule-editor-utils";

interface RuleEditorProps {
  activity: API.LotteryActivity;
  onSaved?: () => void;
}

export default function RuleEditor({ activity, onSaved }: RuleEditorProps) {
  const { t } = useTranslation("lottery");
  const [loading, setLoading] = useState(false);
  const [capsError, setCapsError] = useState<string | null>(null);
  const form = useForm<RuleEditorValues>({
    resolver: zodResolver(getRuleEditorSchema(t)),
    defaultValues: toRuleEditorValues(activity),
  });
  const sourceRows = useFieldArray({
    control: form.control,
    name: "chanceSources",
  });
  const conditionRows = useFieldArray({
    control: form.control,
    name: "conditions",
  });
  const mode = form.watch("mode");
  const advancedJson = form.watch("advancedJson");

  useEffect(() => {
    form.reset(toRuleEditorValues(activity));
    setCapsError(null);
  }, [form, activity]);

  const jsonError = useMemo(
    () => (advancedJson.trim() ? validateJsonTree(advancedJson, t) : null),
    [advancedJson, t]
  );

  async function handleSubmit(values: RuleEditorValues) {
    const eligibility = resolveEligibility(values);
    const capsMessage = buildCapsErrorMessage(t, eligibility);
    setCapsError(capsMessage);
    if (capsMessage) return;
    setLoading(true);
    try {
      await updateLotteryActivityRules({
        id: activity.id,
        eligibility,
        chance_sources: values.chanceSources.map((row) => ({
          source: row.source,
          amount: row.amount,
          daily_limit: row.daily_limit || undefined,
        })),
      });
      toast.success(t("rules.saveSuccess", "Rules saved"));
      onSaved?.();
    } catch (_error) {
      toast.error(t("rules.saveFailed", "Failed to save rules"));
    } finally {
      setLoading(false);
    }
  }

  function handleModeChange(value: string) {
    if (value === "advanced" && !form.getValues("advancedJson").trim()) {
      const tree = buildEligibility(
        form.getValues("op"),
        form.getValues("conditions")
      );
      form.setValue(
        "advancedJson",
        isEmptyEligibility(tree) ? "" : JSON.stringify(tree, null, 2)
      );
    }
    if (value === "simple") {
      const text = form.getValues("advancedJson").trim();
      let simple: ReturnType<typeof treeToSimple> = { op: "AND", rows: [] };
      if (text) {
        try {
          simple = treeToSimple(
            JSON.parse(text) as API.LotteryActivity["eligibility"]
          );
        } catch {
          simple = null;
        }
      }
      if (!simple) {
        toast.error(
          t(
            "rules.cannotSimplify",
            "This rule tree is too complex for simple mode. Please edit it in Advanced mode."
          )
        );
        return;
      }
      form.setValue("op", simple.op);
      form.setValue("conditions", simple.rows);
      form.setValue("advancedJson", "");
    }
    form.setValue("mode", value as RuleEditorValues["mode"]);
  }

  return (
    <Form {...form}>
      <form className="space-y-6" onSubmit={form.handleSubmit(handleSubmit)}>
        <section className="space-y-3">
          <h3 className="font-medium text-base">
            {t("rules.chanceSources", "Chance Sources")}
          </h3>
          <p className="text-muted-foreground text-sm">
            {t(
              "rules.chanceSourcesDescription",
              "Configure how users earn draw chances. Each source can only appear once."
            )}
          </p>
          {sourceRows.fields.map((row, index) => (
            <div className="flex items-start gap-2" key={row.id}>
              <FormField
                control={form.control}
                name={`chanceSources.${index}.source`}
                render={({ field }) => (
                  <FormItem className="flex-1">
                    <Select onValueChange={field.onChange} value={field.value}>
                      <FormControl>
                        <SelectTrigger>
                          <SelectValue
                            placeholder={t(
                              "rules.selectSource",
                              "Select source"
                            )}
                          />
                        </SelectTrigger>
                      </FormControl>
                      <SelectContent>
                        {CHANCE_SOURCE_OPTIONS.map((option) => (
                          <SelectItem key={option.value} value={option.value}>
                            {t(option.labelKey, option.labelDefault)}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name={`chanceSources.${index}.amount`}
                render={({ field }) => (
                  <FormItem className="w-32">
                    <FormControl>
                      <EnhancedInput
                        min={0}
                        onValueChange={(value) => field.onChange(value)}
                        placeholder={t("rules.amount", "Amount")}
                        type="number"
                        value={field.value}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name={`chanceSources.${index}.daily_limit`}
                render={({ field }) => (
                  <FormItem className="w-44">
                    <FormControl>
                      <EnhancedInput
                        min={0}
                        onValueChange={(value) => field.onChange(value)}
                        placeholder={t(
                          "rules.dailyLimit",
                          "Daily limit (optional)"
                        )}
                        type="number"
                        value={field.value}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <Button
                onClick={() => sourceRows.remove(index)}
                size="icon"
                type="button"
                variant="ghost"
              >
                <Trash2Icon className="size-4" />
              </Button>
            </div>
          ))}
          <Button
            onClick={() =>
              sourceRows.append({ source: "daily_signin", amount: 1 })
            }
            size="sm"
            type="button"
            variant="outline"
          >
            <PlusIcon className="size-4" />
            {t("rules.addSource", "Add Source")}
          </Button>
        </section>

        <section className="space-y-3">
          <h3 className="font-medium text-base">
            {t("rules.eligibility", "Eligibility")}
          </h3>
          <Alert className="border-yellow-500/50 bg-yellow-50 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400">
            <TriangleAlertIcon />
            <AlertTitle>
              {t("rules.stage1Warning", "Stage 1 notice")}
            </AlertTitle>
            <AlertDescription className="text-inherit">
              {t(
                "rules.stage1WarningDescription",
                "The rule context is not wired up in the current version (Stage 1). Configuring eligibility will prevent users from joining the lottery. It is recommended to keep it empty."
              )}
            </AlertDescription>
          </Alert>
          <Tabs onValueChange={handleModeChange} value={mode}>
            <TabsList>
              <TabsTrigger value="simple">
                {t("rules.simpleMode", "Simple")}
              </TabsTrigger>
              <TabsTrigger value="advanced">
                {t("rules.advancedMode", "Advanced (JSON)")}
              </TabsTrigger>
            </TabsList>
            <TabsContent className="space-y-3 pt-2" value="simple">
              <FormField
                control={form.control}
                name="op"
                render={({ field }) => (
                  <FormItem className="w-48">
                    <FormLabel>
                      {t("rules.op", "Combine Conditions With")}
                    </FormLabel>
                    <Select onValueChange={field.onChange} value={field.value}>
                      <FormControl>
                        <SelectTrigger>
                          <SelectValue />
                        </SelectTrigger>
                      </FormControl>
                      <SelectContent>
                        <SelectItem value="AND">
                          {t("rules.opAnd", "AND")}
                        </SelectItem>
                        <SelectItem value="OR">
                          {t("rules.opOr", "OR")}
                        </SelectItem>
                      </SelectContent>
                    </Select>
                  </FormItem>
                )}
              />
              {conditionRows.fields.length === 0 && (
                <p className="text-muted-foreground text-sm">
                  {t(
                    "rules.noConditions",
                    "No conditions. Everyone is eligible to join."
                  )}
                </p>
              )}
              {conditionRows.fields.map((row, index) => {
                const type = form.watch(`conditions.${index}.type`);
                return (
                  <div
                    className="flex flex-wrap items-start gap-2 rounded-md border p-3"
                    key={row.id}
                  >
                    <FormField
                      control={form.control}
                      name={`conditions.${index}.type`}
                      render={({ field }) => (
                        <FormItem className="w-56">
                          <Select
                            onValueChange={field.onChange}
                            value={field.value}
                          >
                            <FormControl>
                              <SelectTrigger>
                                <SelectValue />
                              </SelectTrigger>
                            </FormControl>
                            <SelectContent>
                              {CONDITION_TYPES.map((item) => (
                                <SelectItem key={item} value={item}>
                                  {t(`rules.conditionType.${item}`, item)}
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    {CONDITION_PARAM_FIELDS[type].map((param) => (
                      <FormField
                        control={form.control}
                        key={param.key}
                        name={`conditions.${index}.${param.key}`}
                        render={({ field }) => (
                          <FormItem className="w-52">
                            <FormControl>
                              <EnhancedInput
                                min={
                                  param.inputType === "number" ? 0 : undefined
                                }
                                onValueChange={(value) => field.onChange(value)}
                                placeholder={
                                  param.placeholderKey &&
                                  param.placeholderDefault
                                    ? t(
                                        param.placeholderKey,
                                        param.placeholderDefault
                                      )
                                    : t(param.labelKey, param.labelDefault)
                                }
                                type={param.inputType}
                                value={field.value}
                              />
                            </FormControl>
                            <FormMessage />
                          </FormItem>
                        )}
                      />
                    ))}
                    <Button
                      onClick={() => conditionRows.remove(index)}
                      size="icon"
                      type="button"
                      variant="ghost"
                    >
                      <Trash2Icon className="size-4" />
                    </Button>
                  </div>
                );
              })}
              <Button
                onClick={() =>
                  conditionRows.append({ type: "has_subscription" })
                }
                size="sm"
                type="button"
                variant="outline"
              >
                <PlusIcon className="size-4" />
                {t("rules.addCondition", "Add Condition")}
              </Button>
            </TabsContent>
            <TabsContent className="space-y-2 pt-2" value="advanced">
              <FormField
                control={form.control}
                name="advancedJson"
                render={({ field }) => (
                  <FormItem>
                    <FormControl>
                      <Textarea
                        className="min-h-56 font-mono text-sm"
                        onChange={field.onChange}
                        placeholder={t(
                          "rules.jsonPlaceholder",
                          'Rule tree JSON, e.g. {"op":"AND","children":[...]}. Leave empty for no requirement.'
                        )}
                        value={field.value}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              {jsonError && (
                <p className="text-destructive text-sm">
                  {t("rules.jsonInvalid", "Invalid JSON: {{error}}").replace(
                    "{{error}}",
                    jsonError
                  )}
                </p>
              )}
            </TabsContent>
          </Tabs>
        </section>

        {capsError && (
          <Alert variant="destructive">
            <TriangleAlertIcon />
            <AlertTitle>
              {t("rules.capsExceeded", "Rule tree exceeds limits")}
            </AlertTitle>
            <AlertDescription>{capsError}</AlertDescription>
          </Alert>
        )}

        <div className="flex justify-end">
          <Button disabled={loading} type="submit">
            {t("rules.save", "Save Rules")}
          </Button>
        </div>
      </form>
    </Form>
  );
}
