"use client";

import { useEffect, useState } from "react";
import type { AxiosError } from "axios";
import { AlertCircle, Loader2, SlidersHorizontal } from "lucide-react";
import { toast } from "sonner";
import { useRepositories } from "@/di/repository-provider";
import { useApiQuery } from "@/presentation/hooks/use-api-query";
import { useT } from "@/shared/i18n/client";
import { Badge } from "@/presentation/components/ui/badge";
import { Button } from "@/presentation/components/ui/button";
import { Input } from "@/presentation/components/ui/input";
import { Label } from "@/presentation/components/ui/label";
import { Switch } from "@/presentation/components/ui/switch";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/presentation/components/ui/sheet";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/presentation/components/ui/select";
import type {
  AnomalyRuleChannels,
  AnomalyRuleDigest,
  AnomalyRuleOption,
  AnomalyRuleSeverity,
} from "@/domain/entities/anomaly-rule";

interface Props {
  ruleKey: string | null;
  severities: AnomalyRuleOption[];
  digestFrequencies: AnomalyRuleOption[];
  onClose: () => void;
  onChanged?: () => void;
}

const formatValue = (value: number, unit: string | null) => `${value}${unit ? ` ${unit}` : ""}`;

/**
 * One rule's Dadycar defaults: whether it exists for clients, whether it runs
 * for those who never chose, its thresholds, severity and channels — then the
 * clients who changed it and the latest changes.
 */
export function AnomalyRuleSheet({ ruleKey, severities, digestFrequencies, onClose, onChanged }: Props) {
  const t = useT();
  const s = t.pages.anomalyRules.sheet;
  const container = useRepositories();

  const { data, loading, error, refetch } = useApiQuery(
    () => container.anomalyRuleRepository.clients(ruleKey as string),
    { enabled: ruleKey !== null, deps: [ruleKey] }
  );

  const rule = data?.rule;
  const [isActive, setIsActive] = useState(true);
  const [defaultEnabled, setDefaultEnabled] = useState(true);
  const [severity, setSeverity] = useState<AnomalyRuleSeverity>("medium");
  const [channels, setChannels] = useState<AnomalyRuleChannels>({ mobile_push: false, fleet_push: false, email: false, digest_frequency: "none" });
  const [values, setValues] = useState<Record<string, string>>({});
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (!rule) return;
    setIsActive(rule.is_active);
    setDefaultEnabled(rule.default_enabled);
    setSeverity(rule.default_severity);
    setChannels(rule.channels);
    setValues(Object.fromEntries(rule.fields.map((field) => [field.key, String(field.value)])));
    setErrors({});
  }, [rule]);

  const handleSave = async () => {
    if (!rule) return;
    setSaving(true);
    setErrors({});
    try {
      await container.anomalyRuleRepository.update(rule.key, {
        is_active: isActive,
        default_enabled: defaultEnabled,
        default_severity: severity,
        ...channels,
        ...(rule.fields.length > 0
          ? {
              parameter_defaults: Object.fromEntries(
                rule.fields.map((field) => [field.key, values[field.key] === "" || values[field.key] === undefined ? null : Number(values[field.key])])
              ),
            }
          : {}),
      });
      toast.success(s.saved);
      refetch();
      onChanged?.();
    } catch (err) {
      const response = (err as AxiosError<{ message?: string; errors?: Record<string, string[]> }>).response;
      if (response?.status === 422 && response.data?.errors) {
        setErrors(
          Object.fromEntries(
            Object.entries(response.data.errors).map(([field, messages]) => [field.replace(/^parameter_defaults\./, ""), messages?.[0] ?? ""])
          )
        );
      } else {
        toast.error(response?.data?.message ?? s.error);
      }
    } finally {
      setSaving(false);
    }
  };

  const describeChange = (key: string, change: { from: unknown; to: unknown }) => {
    const field = rule?.fields.find((item) => `parameters.${item.key}` === key || `parameter_defaults.${item.key}` === key);
    const label = field?.label ?? key;
    const show = (value: unknown) => (typeof value === "boolean" ? (value ? t.common.yes : t.common.no) : value === null ? "—" : String(value));
    return `${label} : ${show(change.from)} → ${show(change.to)}`;
  };

  return (
    <Sheet open={ruleKey !== null} onOpenChange={(open) => !open && onClose()}>
      <SheetContent className="sm:max-w-xl w-[560px] overflow-y-auto flex flex-col h-full border-l border-border bg-card p-0">
        <SheetHeader className="border-b border-border p-6 pb-4">
          <SheetTitle className="flex items-center gap-3">
            <SlidersHorizontal className="w-5 h-5 text-primary" />
            <span>{rule?.name ?? s.title}</span>
          </SheetTitle>
        </SheetHeader>

        {loading ? (
          <div className="flex-1 flex items-center justify-center">
            <Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
          </div>
        ) : error ? (
          <div className="flex-1 flex flex-col items-center justify-center p-6 text-center">
            <AlertCircle className="w-8 h-8 text-destructive mb-3" />
            <p className="text-sm font-semibold text-destructive">{error}</p>
            <Button variant="outline" size="sm" onClick={refetch} className="mt-4">{t.common.retry}</Button>
          </div>
        ) : rule ? (
          <div className="flex-1 overflow-y-auto p-6 space-y-6">
            <p className="text-xs text-muted-foreground leading-relaxed">{s.intro}</p>

            <div className="bg-muted/40 border border-border/80 rounded-xl p-4">
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">{s.condition}</p>
              <p className="text-sm text-foreground mt-1">{rule.condition}</p>
              {rule.explanation && <p className="text-xs text-muted-foreground mt-2">{rule.explanation}</p>}
            </div>

            <div className="space-y-3">
              <div className="flex items-start justify-between gap-4">
                <div>
                  <Label>{s.available}</Label>
                  <p className="text-xs text-muted-foreground mt-0.5">{s.availableHint}</p>
                </div>
                <Switch checked={isActive} onCheckedChange={setIsActive} />
              </div>
              <div className="flex items-start justify-between gap-4">
                <div>
                  <Label>{s.enabledByDefault}</Label>
                  <p className="text-xs text-muted-foreground mt-0.5">{s.enabledByDefaultHint}</p>
                </div>
                <Switch checked={defaultEnabled} onCheckedChange={setDefaultEnabled} disabled={!isActive} />
              </div>
            </div>

            <div className="space-y-3">
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">{s.thresholds}</p>
              {rule.fields.length === 0 ? (
                <p className="text-xs text-muted-foreground">{s.noThreshold}</p>
              ) : (
                <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                  {rule.fields.map((field) => (
                    <div key={field.key} className="space-y-1.5">
                      <Label htmlFor={`threshold-${field.key}`}>{field.label}</Label>
                      <div className="flex items-center gap-2">
                        <Input
                          id={`threshold-${field.key}`}
                          type="number"
                          min={field.min}
                          max={field.max}
                          step={field.step}
                          value={values[field.key] ?? ""}
                          onChange={(e) => setValues((current) => ({ ...current, [field.key]: e.target.value }))}
                        />
                        {field.unit && <span className="text-xs text-muted-foreground shrink-0">{field.unit}</span>}
                      </div>
                      <p className={`text-[11px] ${errors[field.key] ? "text-destructive" : "text-muted-foreground"}`}>
                        {errors[field.key] || `${s.factory(formatValue(field.factory_default, field.unit))} · ${field.min}–${formatValue(field.max, field.unit)}`}
                      </p>
                    </div>
                  ))}
                </div>
              )}
            </div>

            <div className="space-y-1.5">
              <Label>{s.severity}</Label>
              <Select value={severity} onValueChange={(value) => setSeverity(value as AnomalyRuleSeverity)}>
                <SelectTrigger className="h-9"><SelectValue /></SelectTrigger>
                <SelectContent>
                  {severities.map((option) => (
                    <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {rule.sets_own_severity && <p className="text-[11px] text-muted-foreground">{s.severityByCaseHint}</p>}
            </div>

            <div className="space-y-3">
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">{s.notifications}</p>
              {([
                ["mobile_push", s.mobile],
                ["fleet_push", s.fleet],
                ["email", s.email],
              ] as const).map(([key, label]) => (
                <div key={key} className="flex items-center justify-between gap-4">
                  <Label>{label}</Label>
                  <Switch checked={channels[key]} onCheckedChange={(checked) => setChannels((current) => ({ ...current, [key]: checked }))} />
                </div>
              ))}
              <div className="space-y-1.5">
                <Label>{s.emailSending}</Label>
                <Select
                  value={channels.digest_frequency}
                  onValueChange={(value) => setChannels((current) => ({ ...current, digest_frequency: value as AnomalyRuleDigest }))}
                  disabled={!channels.email}
                >
                  <SelectTrigger className="h-9"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    {digestFrequencies.map((option) => (
                      <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            </div>

            <Button onClick={handleSave} disabled={saving} className="w-full">
              {saving && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
              {s.save}
            </Button>

            <div className="space-y-2 pt-2 border-t border-border">
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground pt-4">
                {s.clientsTitle} ({data?.clients.length ?? 0})
              </p>
              {(data?.clients.length ?? 0) === 0 ? (
                <p className="text-xs text-muted-foreground">{s.noClients}</p>
              ) : (
                data?.clients.map((client) => (
                  <div key={client.company_id} className="border border-border rounded-lg p-3">
                    <div className="flex items-center justify-between gap-2">
                      <span className="text-sm font-medium text-foreground">{client.company_name ?? `#${client.company_id}`}</span>
                      {!client.enabled && <Badge variant="secondary" className="text-[10px]">{s.clientOff}</Badge>}
                    </div>
                    {client.changed_fields.length > 0 && (
                      <p className="text-xs text-muted-foreground mt-1">
                        {client.changed_fields.map((field) => `${field.label} : ${formatValue(field.value, field.unit)} (${formatValue(field.default, field.unit)})`).join(" · ")}
                      </p>
                    )}
                    <p className="text-[11px] text-muted-foreground mt-1">
                      {[client.updated_by, client.updated_at ? new Date(client.updated_at).toLocaleString() : null].filter(Boolean).join(" · ")}
                    </p>
                  </div>
                ))
              )}
            </div>

            <div className="space-y-2">
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">{s.historyTitle}</p>
              {(data?.history.length ?? 0) === 0 ? (
                <p className="text-xs text-muted-foreground">{s.noHistory}</p>
              ) : (
                data?.history.map((change, index) => (
                  <div key={index} className="text-xs border-l-2 border-border pl-3 py-1">
                    <p className="text-foreground font-medium">
                      {change.scope === "dadycar" ? s.dadycar : change.company_name ?? "—"}
                      {change.user ? ` · ${change.user}` : ""}
                      {change.created_at ? ` · ${new Date(change.created_at).toLocaleString()}` : ""}
                    </p>
                    <p className="text-muted-foreground">
                      {change.action === "reset"
                        ? s.resetAction
                        : Object.entries(change.changes).map(([key, value]) => describeChange(key, value)).join(" · ")}
                    </p>
                  </div>
                ))
              )}
            </div>
          </div>
        ) : null}
      </SheetContent>
    </Sheet>
  );
}
