import type { Torrent } from '../shared';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { LIMIT_MODE, PRIORITY } from '../shared';
import { useTorrentMutations } from '../useTransmissionData';

// Per-torrent bandwidth, seeding and peer options — the reference client's "other settings" dialog.
//
// Every limit here is a pair (a boolean and a number) because Transmission stores them that way: turning a
// limit off keeps the number, so unchecking and re-checking gets you back the value you had.

type TorrentOptionsDialogProps = { open: boolean; onOpenChange: (open: boolean) => void; targets: Torrent[] };

type FormState = {
  bandwidthPriority: string;
  honorsSessionLimits: boolean;
  downloadLimited: boolean;
  downloadLimit: string;
  uploadLimited: boolean;
  uploadLimit: string;
  seedRatioMode: string;
  seedRatioLimit: string;
  seedIdleMode: string;
  seedIdleLimit: string;
  peerLimit: string;
  sequential: boolean;
};

const fromTorrent = (t: Torrent): FormState => ({
  bandwidthPriority: String(t.bandwidthPriority ?? 0),
  honorsSessionLimits: t.honorsSessionLimits ?? true,
  downloadLimited: t.downloadLimited ?? false,
  downloadLimit: String(t.downloadLimit ?? 0),
  uploadLimited: t.uploadLimited ?? false,
  uploadLimit: String(t.uploadLimit ?? 0),
  seedRatioMode: String(t.seedRatioMode ?? 0),
  seedRatioLimit: String(t.seedRatioLimit ?? 2),
  seedIdleMode: String(t.seedIdleMode ?? 0),
  seedIdleLimit: String(t.seedIdleLimit ?? 30),
  peerLimit: String(t['peer-limit'] ?? 50),
  sequential: t.sequential_download ?? false,
});

export const TorrentOptionsDialog = ({ open, onOpenChange, targets }: TorrentOptionsDialogProps) => {
  const { set } = useTorrentMutations();
  const [form, setForm] = useState<FormState | null>(null);

  useEffect(() => {
    // Seeded from the first target. With a mixed selection the others' values are simply overwritten —
    // which is what "apply these settings to all of them" means, and the header says so.
    if (open && targets[0]) setForm(fromTorrent(targets[0]));
  }, [open, targets]);

  if (!form) return null;

  const patch = (next: Partial<FormState>) => setForm((prev) => (prev ? { ...prev, ...next } : prev));

  const submit = async () => {
    await set.mutateAsync({
      ids: targets.map((t) => t.id),
      bandwidthPriority: Number(form.bandwidthPriority),
      honorsSessionLimits: form.honorsSessionLimits,
      downloadLimited: form.downloadLimited,
      downloadLimit: Math.max(0, Number(form.downloadLimit) || 0),
      uploadLimited: form.uploadLimited,
      uploadLimit: Math.max(0, Number(form.uploadLimit) || 0),
      seedRatioMode: Number(form.seedRatioMode),
      seedRatioLimit: Math.max(0, Number(form.seedRatioLimit) || 0),
      seedIdleMode: Number(form.seedIdleMode),
      seedIdleLimit: Math.max(0, Number(form.seedIdleLimit) || 0),
      'peer-limit': Math.max(1, Number(form.peerLimit) || 1),
      sequential_download: form.sequential,
    });
    onOpenChange(false);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>Torrent options</DialogTitle>
          <DialogDescription>
            {targets.length === 1
              ? targets[0]!.name
              : `Applying to ${targets.length} torrents — all of them will take these values.`}
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-5">
          <section className="space-y-3">
            <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Bandwidth</h3>
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1.5">
                <Label htmlFor="tr-opt-priority">Priority</Label>
                <Select value={form.bandwidthPriority} onValueChange={(v) => patch({ bandwidthPriority: v })}>
                  <SelectTrigger id="tr-opt-priority">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value={String(PRIORITY.High)}>High</SelectItem>
                    <SelectItem value={String(PRIORITY.Normal)}>Normal</SelectItem>
                    <SelectItem value={String(PRIORITY.Low)}>Low</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="tr-opt-peers">Maximum peers</Label>
                <Input
                  id="tr-opt-peers"
                  type="number"
                  min={1}
                  value={form.peerLimit}
                  onChange={(ev) => patch({ peerLimit: ev.target.value })}
                />
              </div>
            </div>

            <LimitRow
              id="tr-opt-down"
              label="Limit download speed"
              enabled={form.downloadLimited}
              value={form.downloadLimit}
              onToggle={(v) => patch({ downloadLimited: v })}
              onChange={(v) => patch({ downloadLimit: v })}
            />
            <LimitRow
              id="tr-opt-up"
              label="Limit upload speed"
              enabled={form.uploadLimited}
              value={form.uploadLimit}
              onToggle={(v) => patch({ uploadLimited: v })}
              onChange={(v) => patch({ uploadLimit: v })}
            />

            <label className="flex items-center gap-2 text-sm">
              <Checkbox
                checked={form.honorsSessionLimits}
                onCheckedChange={(v) => patch({ honorsSessionLimits: v === true })}
              />
              Honour the global speed limits
            </label>
            <label className="flex items-center gap-2 text-sm">
              <Checkbox checked={form.sequential} onCheckedChange={(v) => patch({ sequential: v === true })} />
              Download pieces in order
            </label>
          </section>

          <section className="space-y-3">
            <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Stop seeding when</h3>
            <div className="grid grid-cols-[1fr_120px] items-end gap-3">
              <div className="space-y-1.5">
                <Label htmlFor="tr-opt-ratio-mode">Ratio reaches</Label>
                <Select value={form.seedRatioMode} onValueChange={(v) => patch({ seedRatioMode: v })}>
                  <SelectTrigger id="tr-opt-ratio-mode">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value={String(LIMIT_MODE.Global)}>Use the global setting</SelectItem>
                    <SelectItem value={String(LIMIT_MODE.Single)}>Use this value</SelectItem>
                    <SelectItem value={String(LIMIT_MODE.Unlimited)}>Seed forever</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <Input
                type="number"
                step="0.1"
                min={0}
                disabled={form.seedRatioMode !== String(LIMIT_MODE.Single)}
                value={form.seedRatioLimit}
                onChange={(ev) => patch({ seedRatioLimit: ev.target.value })}
              />
            </div>

            <div className="grid grid-cols-[1fr_120px] items-end gap-3">
              <div className="space-y-1.5">
                <Label htmlFor="tr-opt-idle-mode">Idle for (minutes)</Label>
                <Select value={form.seedIdleMode} onValueChange={(v) => patch({ seedIdleMode: v })}>
                  <SelectTrigger id="tr-opt-idle-mode">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value={String(LIMIT_MODE.Global)}>Use the global setting</SelectItem>
                    <SelectItem value={String(LIMIT_MODE.Single)}>Use this value</SelectItem>
                    <SelectItem value={String(LIMIT_MODE.Unlimited)}>Never stop</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <Input
                type="number"
                min={0}
                disabled={form.seedIdleMode !== String(LIMIT_MODE.Single)}
                value={form.seedIdleLimit}
                onChange={(ev) => patch({ seedIdleLimit: ev.target.value })}
              />
            </div>
          </section>
        </div>

        <DialogFooter>
          <Button variant="ghost" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button onClick={submit} disabled={set.isPending}>
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

type LimitRowProps = {
  id: string;
  label: string;
  enabled: boolean;
  value: string;
  onToggle: (enabled: boolean) => void;
  onChange: (value: string) => void;
};

const LimitRow = ({ id, label, enabled, value, onToggle, onChange }: LimitRowProps) => (
  <div className="flex items-center gap-3">
    <label className="flex flex-1 items-center gap-2 text-sm">
      <Checkbox checked={enabled} onCheckedChange={(v) => onToggle(v === true)} />
      {label}
    </label>
    <Input
      id={id}
      type="number"
      min={0}
      disabled={!enabled}
      value={value}
      onChange={(ev) => onChange(ev.target.value)}
      className="w-28"
    />
    <span className="w-10 text-xs text-muted-foreground">kB/s</span>
  </div>
);
