"use client";

import { useState, useEffect } from "react";
import { Trash2, Plus, ChevronDown, ChevronUp } from "lucide-react";
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import type {
  ChannelResponse,
  ProgrammingBlock,
  BlockContent,
  FillStrategy,
  ContentType,
  MediaFilter,
  RecyclePolicy,
} from "@/lib/types";

// ---------------------------------------------------------------------------
// Sub-components (all dumb, no hooks)
// ---------------------------------------------------------------------------

interface FieldProps {
  label: string;
  hint?: string;
  children: React.ReactNode;
}

function Field({ label, hint, children }: FieldProps) {
  return (
    <div className="space-y-1.5">
      <label className="block text-xs font-medium text-zinc-400">{label}</label>
      {children}
      {hint && <p className="text-[11px] text-zinc-600">{hint}</p>}
    </div>
  );
}

function TextInput({
  value,
  onChange,
  placeholder,
  required,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  required?: boolean;
}) {
  return (
    <input
      required={required}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      className="w-full rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-600 focus:border-zinc-500 focus:outline-none"
    />
  );
}

function NumberInput({
  value,
  onChange,
  min,
  max,
  step,
  placeholder,
}: {
  value: number | "";
  onChange: (v: number | "") => void;
  min?: number;
  max?: number;
  step?: number | "any";
  placeholder?: string;
}) {
  return (
    <input
      type="number"
      min={min}
      max={max}
      step={step}
      value={value}
      placeholder={placeholder}
      onChange={(e) =>
        onChange(e.target.value === "" ? "" : Number(e.target.value))
      }
      className="w-full rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-600 focus:border-zinc-500 focus:outline-none"
    />
  );
}

function NativeSelect({
  value,
  onChange,
  children,
}: {
  value: string;
  onChange: (v: string) => void;
  children: React.ReactNode;
}) {
  return (
    <select
      value={value}
      onChange={(e) => onChange(e.target.value)}
      className="w-full rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 focus:border-zinc-500 focus:outline-none"
    >
      {children}
    </select>
  );
}

// ---------------------------------------------------------------------------
// Block editor
// ---------------------------------------------------------------------------

function defaultFilter(): MediaFilter {
  return {
    content_type: null,
    genres: [],
    decade: null,
    tags: [],
    min_duration_secs: null,
    max_duration_secs: null,
    collections: [],
  };
}

function defaultBlock(): ProgrammingBlock {
  return {
    id: crypto.randomUUID(),
    name: "",
    start_time: "20:00:00",
    duration_mins: 60,
    content: {
      type: "algorithmic",
      filter: defaultFilter(),
      strategy: "random",
    },
  };
}

interface BlockEditorProps {
  block: ProgrammingBlock;
  onChange: (block: ProgrammingBlock) => void;
  onRemove: () => void;
}

function BlockEditor({ block, onChange, onRemove }: BlockEditorProps) {
  const [expanded, setExpanded] = useState(true);

  const setField = <K extends keyof ProgrammingBlock>(
    key: K,
    value: ProgrammingBlock[K],
  ) => onChange({ ...block, [key]: value });

  const content = block.content;

  const setContentType = (type: "algorithmic" | "manual") => {
    if (type === "algorithmic") {
      onChange({
        ...block,
        content: { type: "algorithmic", filter: defaultFilter(), strategy: "random" },
      });
    } else {
      onChange({ ...block, content: { type: "manual", items: [] } });
    }
  };

  const setFilter = (patch: Partial<MediaFilter>) => {
    if (content.type !== "algorithmic") return;
    onChange({
      ...block,
      content: { ...content, filter: { ...content.filter, ...patch } },
    });
  };

  const setStrategy = (strategy: FillStrategy) => {
    if (content.type !== "algorithmic") return;
    onChange({ ...block, content: { ...content, strategy } });
  };

  return (
    <div className="rounded-lg border border-zinc-700 bg-zinc-800/50">
      {/* Block header */}
      <div className="flex items-center gap-2 px-3 py-2">
        <button
          type="button"
          onClick={() => setExpanded((v) => !v)}
          className="flex flex-1 items-center gap-2 text-left text-sm font-medium text-zinc-200"
        >
          {expanded ? (
            <ChevronUp className="size-3.5 shrink-0 text-zinc-500" />
          ) : (
            <ChevronDown className="size-3.5 shrink-0 text-zinc-500" />
          )}
          <span className="truncate">{block.name || "Unnamed block"}</span>
          <span className="shrink-0 font-mono text-[11px] text-zinc-500">
            {block.start_time.slice(0, 5)} · {block.duration_mins}m
          </span>
        </button>
        <button
          type="button"
          onClick={onRemove}
          className="rounded p-1 text-zinc-600 hover:bg-zinc-700 hover:text-red-400"
        >
          <Trash2 className="size-3.5" />
        </button>
      </div>

      {expanded && (
        <div className="space-y-3 border-t border-zinc-700 px-3 py-3">
          <div className="grid grid-cols-2 gap-3">
            <Field label="Block name">
              <TextInput
                value={block.name}
                onChange={(v) => setField("name", v)}
                placeholder="Evening Sitcoms"
              />
            </Field>
            <Field label="Content type">
              <NativeSelect
                value={content.type}
                onChange={(v) => setContentType(v as "algorithmic" | "manual")}
              >
                <option value="algorithmic">Algorithmic</option>
                <option value="manual">Manual</option>
              </NativeSelect>
            </Field>
          </div>

          <div className="grid grid-cols-2 gap-3">
            <Field label="Start time">
              <input
                type="time"
                value={block.start_time.slice(0, 5)}
                onChange={(e) => setField("start_time", e.target.value + ":00")}
                className="w-full rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 focus:border-zinc-500 focus:outline-none"
              />
            </Field>
            <Field label="Duration (minutes)">
              <NumberInput
                value={block.duration_mins}
                onChange={(v) => setField("duration_mins", v === "" ? 60 : v)}
                min={1}
              />
            </Field>
          </div>

          {content.type === "algorithmic" && (
            <div className="space-y-3 rounded-md border border-zinc-700/50 bg-zinc-800 p-3">
              <p className="text-[11px] font-medium uppercase tracking-wider text-zinc-500">
                Filter
              </p>

              <div className="grid grid-cols-2 gap-3">
                <Field label="Media type">
                  <NativeSelect
                    value={content.filter.content_type ?? ""}
                    onChange={(v) =>
                      setFilter({
                        content_type: v === "" ? null : (v as ContentType),
                      })
                    }
                  >
                    <option value="">Any</option>
                    <option value="movie">Movie</option>
                    <option value="episode">Episode</option>
                    <option value="short">Short</option>
                  </NativeSelect>
                </Field>

                <Field label="Strategy">
                  <NativeSelect
                    value={content.strategy}
                    onChange={(v) => setStrategy(v as FillStrategy)}
                  >
                    <option value="random">Random</option>
                    <option value="best_fit">Best fit</option>
                    <option value="sequential">Sequential</option>
                  </NativeSelect>
                </Field>
              </div>

              <Field
                label="Genres"
                hint="Comma-separated, e.g. Comedy, Action"
              >
                <TextInput
                  value={content.filter.genres.join(", ")}
                  onChange={(v) =>
                    setFilter({
                      genres: v
                        .split(",")
                        .map((s) => s.trim())
                        .filter(Boolean),
                    })
                  }
                  placeholder="Comedy, Sci-Fi"
                />
              </Field>

              <div className="grid grid-cols-3 gap-3">
                <Field label="Decade" hint="e.g. 1990">
                  <NumberInput
                    value={content.filter.decade ?? ""}
                    onChange={(v) =>
                      setFilter({ decade: v === "" ? null : (v as number) })
                    }
                    placeholder="1990"
                  />
                </Field>
                <Field label="Min duration (s)">
                  <NumberInput
                    value={content.filter.min_duration_secs ?? ""}
                    onChange={(v) =>
                      setFilter({
                        min_duration_secs: v === "" ? null : (v as number),
                      })
                    }
                    placeholder="1200"
                  />
                </Field>
                <Field label="Max duration (s)">
                  <NumberInput
                    value={content.filter.max_duration_secs ?? ""}
                    onChange={(v) =>
                      setFilter({
                        max_duration_secs: v === "" ? null : (v as number),
                      })
                    }
                    placeholder="3600"
                  />
                </Field>
              </div>

              <Field
                label="Collections"
                hint="Jellyfin library IDs, comma-separated"
              >
                <TextInput
                  value={content.filter.collections.join(", ")}
                  onChange={(v) =>
                    setFilter({
                      collections: v
                        .split(",")
                        .map((s) => s.trim())
                        .filter(Boolean),
                    })
                  }
                  placeholder="abc123"
                />
              </Field>
            </div>
          )}

          {content.type === "manual" && (
            <div className="space-y-2 rounded-md border border-zinc-700/50 bg-zinc-800 p-3">
              <p className="text-[11px] font-medium uppercase tracking-wider text-zinc-500">
                Item IDs
              </p>
              <textarea
                rows={3}
                value={content.items.join("\n")}
                onChange={(e) =>
                  onChange({
                    ...block,
                    content: {
                      type: "manual",
                      items: e.target.value
                        .split("\n")
                        .map((s) => s.trim())
                        .filter(Boolean),
                    },
                  })
                }
                placeholder={"abc123\ndef456\nghi789"}
                className="w-full resize-none rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 font-mono text-xs text-zinc-100 placeholder:text-zinc-600 focus:border-zinc-500 focus:outline-none"
              />
              <p className="text-[11px] text-zinc-600">
                One Jellyfin item ID per line, played in order.
              </p>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Recycle policy editor
// ---------------------------------------------------------------------------

interface RecyclePolicyEditorProps {
  policy: RecyclePolicy;
  onChange: (policy: RecyclePolicy) => void;
}

function RecyclePolicyEditor({ policy, onChange }: RecyclePolicyEditorProps) {
  return (
    <div className="space-y-3">
      <div className="grid grid-cols-2 gap-3">
        <Field label="Cooldown (days)" hint="Don't replay within N days">
          <NumberInput
            value={policy.cooldown_days ?? ""}
            onChange={(v) =>
              onChange({
                ...policy,
                cooldown_days: v === "" ? null : (v as number),
              })
            }
            min={0}
            placeholder="7"
          />
        </Field>
        <Field
          label="Cooldown (generations)"
          hint="Don't replay within N schedules"
        >
          <NumberInput
            value={policy.cooldown_generations ?? ""}
            onChange={(v) =>
              onChange({
                ...policy,
                cooldown_generations: v === "" ? null : (v as number),
              })
            }
            min={0}
            placeholder="3"
          />
        </Field>
      </div>
      <Field
        label="Min available ratio"
        hint="0.0–1.0. Keep at least this fraction of the pool selectable even if cooldown hasn't expired"
      >
        <NumberInput
          value={policy.min_available_ratio}
          onChange={(v) =>
            onChange({
              ...policy,
              min_available_ratio: v === "" ? 0.1 : (v as number),
            })
          }
          min={0}
          max={1}
          step={0.01}
          placeholder="0.1"
        />
      </Field>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Main sheet
// ---------------------------------------------------------------------------

interface EditChannelSheetProps {
  channel: ChannelResponse | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (
    id: string,
    data: {
      name: string;
      description: string;
      timezone: string;
      schedule_config: { blocks: ProgrammingBlock[] };
      recycle_policy: RecyclePolicy;
    },
  ) => void;
  isPending: boolean;
  error?: string | null;
}

export function EditChannelSheet({
  channel,
  open,
  onOpenChange,
  onSubmit,
  isPending,
  error,
}: EditChannelSheetProps) {
  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [timezone, setTimezone] = useState("UTC");
  const [blocks, setBlocks] = useState<ProgrammingBlock[]>([]);
  const [recyclePolicy, setRecyclePolicy] = useState<RecyclePolicy>({
    cooldown_days: null,
    cooldown_generations: null,
    min_available_ratio: 0.1,
  });

  // Sync from channel whenever it changes or sheet opens
  useEffect(() => {
    if (channel) {
      setName(channel.name);
      setDescription(channel.description ?? "");
      setTimezone(channel.timezone);
      setBlocks(channel.schedule_config.blocks);
      setRecyclePolicy(channel.recycle_policy);
    }
  }, [channel]);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!channel) return;
    onSubmit(channel.id, {
      name,
      description,
      timezone,
      schedule_config: { blocks },
      recycle_policy: recyclePolicy,
    });
  };

  const addBlock = () => setBlocks((prev) => [...prev, defaultBlock()]);

  const updateBlock = (idx: number, block: ProgrammingBlock) =>
    setBlocks((prev) => prev.map((b, i) => (i === idx ? block : b)));

  const removeBlock = (idx: number) =>
    setBlocks((prev) => prev.filter((_, i) => i !== idx));

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent
        side="right"
        className="flex w-full flex-col gap-0 border-zinc-800 bg-zinc-900 p-0 text-zinc-100 sm:max-w-xl"
      >
        <SheetHeader className="border-b border-zinc-800 px-6 py-4">
          <SheetTitle className="text-zinc-100">Edit channel</SheetTitle>
        </SheetHeader>

        <form
          onSubmit={handleSubmit}
          className="flex flex-1 flex-col overflow-hidden"
        >
          <div className="flex-1 space-y-6 overflow-y-auto px-6 py-4">
            {/* Basic info */}
            <section className="space-y-3">
              <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                Basic info
              </h3>

              <Field label="Name">
                <TextInput
                  required
                  value={name}
                  onChange={setName}
                  placeholder="90s Sitcom Network"
                />
              </Field>

              <Field label="Timezone" hint="IANA timezone, e.g. America/New_York">
                <TextInput
                  required
                  value={timezone}
                  onChange={setTimezone}
                  placeholder="UTC"
                />
              </Field>

              <Field label="Description">
                <textarea
                  value={description}
                  onChange={(e) => setDescription(e.target.value)}
                  rows={2}
                  placeholder="Nothing but classic sitcoms, all day"
                  className="w-full resize-none rounded-md border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-600 focus:border-zinc-500 focus:outline-none"
                />
              </Field>
            </section>

            {/* Programming blocks */}
            <section className="space-y-3">
              <div className="flex items-center justify-between">
                <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                  Programming blocks
                </h3>
                <Button
                  type="button"
                  variant="outline"
                  size="xs"
                  onClick={addBlock}
                  className="border-zinc-700 text-zinc-300 hover:text-zinc-100"
                >
                  <Plus className="size-3" />
                  Add block
                </Button>
              </div>

              {blocks.length === 0 && (
                <p className="rounded-md border border-dashed border-zinc-700 px-4 py-6 text-center text-xs text-zinc-600">
                  No blocks yet. Gaps between blocks show no-signal.
                </p>
              )}

              <div className="space-y-2">
                {blocks.map((block, idx) => (
                  <BlockEditor
                    key={block.id}
                    block={block}
                    onChange={(b) => updateBlock(idx, b)}
                    onRemove={() => removeBlock(idx)}
                  />
                ))}
              </div>
            </section>

            {/* Recycle policy */}
            <section className="space-y-3">
              <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                Recycle policy
              </h3>
              <RecyclePolicyEditor
                policy={recyclePolicy}
                onChange={setRecyclePolicy}
              />
            </section>
          </div>

          {/* Footer */}
          <div className="flex items-center justify-between border-t border-zinc-800 px-6 py-4">
            {error && <p className="text-xs text-red-400">{error}</p>}
            <div className="ml-auto flex gap-2">
              <Button
                type="button"
                variant="ghost"
                onClick={() => onOpenChange(false)}
                disabled={isPending}
              >
                Cancel
              </Button>
              <Button type="submit" disabled={isPending}>
                {isPending ? "Saving…" : "Save changes"}
              </Button>
            </div>
          </div>
        </form>
      </SheetContent>
    </Sheet>
  );
}
