"use client";

import { useState } from "react";
import { Trash2, Plus } from "lucide-react";
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { BlockTimeline, BLOCK_COLORS } from "./block-timeline";
import { AlgorithmicFilterEditor } from "./algorithmic-filter-editor";
import { RotationPolicyEditor } from "./rotation-policy-editor";
import { WebhookEditor } from "./webhook-editor";
import { AccessSettingsEditor } from "./access-settings-editor";
import { LogoEditor } from "./logo-editor";
import { ConfigHistorySheet } from "./config-history-sheet";
import { useChannelForm } from "@/hooks/use-channel-form";
import { channelFormSchema, extractErrors } from "@/lib/schemas";
import type { FieldErrors } from "@/lib/schemas";
import type {
  AccessMode,
  ChannelResponse,
  LogoPosition,
  ProgrammingBlock,
  FillStrategy,
  MediaFilter,
  ProviderInfo,
  RotationPolicy,
  Weekday,
} from "@/lib/types";
import { WEEKDAYS, WEEKDAY_LABELS } from "@/lib/types";
import { cn } from "@/lib/utils";

// ---------------------------------------------------------------------------
// Local shared primitives (only used inside this file)
// ---------------------------------------------------------------------------

function Field({
  label,
  hint,
  error,
  children,
}: {
  label: string;
  hint?: string;
  error?: string;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <label className="block text-xs font-medium text-zinc-400">{label}</label>
      {children}
      {error ? (
        <p className="text-[11px] text-red-400">{error}</p>
      ) : hint ? (
        <p className="text-[11px] text-zinc-600">{hint}</p>
      ) : null}
    </div>
  );
}

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

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

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>
  );
}

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

// ---------------------------------------------------------------------------
// BlockEditor — inline because it's only used here and depends on local types
// ---------------------------------------------------------------------------

interface BlockEditorProps {
  block: ProgrammingBlock;
  index: number;
  errors: FieldErrors;
  providers: ProviderInfo[];
  onChange: (block: ProgrammingBlock) => void;
}

function BlockEditor({ block, index, errors, providers, onChange }: BlockEditorProps) {
  const setField = <K extends keyof ProgrammingBlock>(key: K, value: ProgrammingBlock[K]) =>
    onChange({ ...block, [key]: value });

  const content = block.content;
  const pfx = `blocks.${index}`;

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

  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 } });
  };

  const setProviderId = (id: string) =>
    onChange({ ...block, content: { ...content, provider_id: id } });

  return (
    <div className="space-y-3">
      <div className="grid grid-cols-2 gap-3">
        <Field label="Block name" error={errors[`${pfx}.name`]}>
          <TextInput
            value={block.name}
            onChange={(v) => setField("name", v)}
            placeholder="Evening Sitcoms"
            error={!!errors[`${pfx}.name`]}
          />
        </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)" error={errors[`${pfx}.duration_mins`]}>
          <NumberInput
            value={block.duration_mins}
            onChange={(v) => setField("duration_mins", v === "" ? 60 : v)}
            min={1}
            error={!!errors[`${pfx}.duration_mins`]}
          />
        </Field>
      </div>

      {content.type === "algorithmic" && (
        <>
          <AlgorithmicFilterEditor
            content={content}
            pfx={pfx}
            errors={errors}
            providers={providers}
            setFilter={setFilter}
            setStrategy={setStrategy}
            setProviderId={setProviderId}
          />

          {content.strategy === "sequential" && (
            <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">
                Sequential options
              </p>
              <label className="flex cursor-pointer items-center gap-2">
                <input
                  type="checkbox"
                  checked={block.loop_on_finish ?? true}
                  onChange={(e) =>
                    onChange({ ...block, loop_on_finish: e.target.checked })
                  }
                  className="accent-zinc-400"
                />
                <span className="text-sm text-zinc-300">Loop series</span>
                <span className="text-[11px] text-zinc-600">
                  Restart from episode 1 after the final episode
                </span>
              </label>
              <label className="flex cursor-pointer items-center gap-2">
                <input
                  type="checkbox"
                  checked={block.ignore_rotation_policy ?? false}
                  onChange={(e) =>
                    onChange({ ...block, ignore_rotation_policy: e.target.checked })
                  }
                  className="accent-zinc-400"
                />
                <span className="text-sm text-zinc-300">Independent scheduling</span>
                <span className="text-[11px] text-zinc-600">
                  Play episodes in order even if they aired in another block today
                </span>
              </label>
            </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 item ID per line, played in order.
          </p>
        </div>
      )}

      <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">
          Block access
        </p>
        <AccessSettingsEditor
          accessMode={(block.access_mode as AccessMode) ?? "public"}
          accessPassword={block.access_password ?? ""}
          onAccessModeChange={(m) => onChange({ ...block, access_mode: m })}
          onAccessPasswordChange={(pw) => onChange({ ...block, access_password: pw })}
          label="Access mode"
          passwordLabel="Block password"
          passwordHint="Leave blank to keep existing"
        />
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// EditChannelSheet
// ---------------------------------------------------------------------------

interface EditChannelSheetProps {
  channel: ChannelResponse | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (
    id: string,
    data: {
      name: string;
      description: string;
      timezone: string;
      schedule_config: { day_blocks: Record<Weekday, ProgrammingBlock[]> };
      rotation_policy: RotationPolicy;
      auto_schedule: boolean;
      access_mode?: string;
      logo?: string | null;
      logo_position?: string;
      logo_opacity?: number;
      webhook_url?: string | null;
      webhook_poll_interval_secs?: number;
      webhook_body_template?: string | null;
      webhook_headers?: string | null;
    },
  ) => void;
  isPending: boolean;
  error?: string | null;
  providers?: ProviderInfo[];
}

export function EditChannelSheet({
  channel,
  open,
  onOpenChange,
  onSubmit,
  isPending,
  error,
  providers = [],
}: EditChannelSheetProps) {
  const form = useChannelForm(channel);
  const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
  const [activeDay, setActiveDay] = useState<Weekday>('monday');
  const [copyTarget, setCopyTarget] = useState<Weekday | 'all' | ''>('');
  const [configHistoryOpen, setConfigHistoryOpen] = useState(false);

  const handleCopyTo = () => {
    if (!copyTarget) return;
    const sourceBlocks = form.dayBlocks[activeDay] ?? [];
    if (copyTarget === 'all') {
      const newDayBlocks = { ...form.dayBlocks };
      for (const day of WEEKDAYS) {
        if (day !== activeDay) {
          newDayBlocks[day] = sourceBlocks.map(b => ({ ...b, id: crypto.randomUUID() }));
        }
      }
      form.setDayBlocks(newDayBlocks);
    } else {
      form.setDayBlocks({
        ...form.dayBlocks,
        [copyTarget]: sourceBlocks.map(b => ({ ...b, id: crypto.randomUUID() })),
      });
    }
    setCopyTarget('');
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!channel) return;

    const result = channelFormSchema.safeParse({
      name: form.name,
      description: form.description,
      timezone: form.timezone,
      day_blocks: form.dayBlocks,
      rotation_policy: form.rotationPolicy,
      auto_schedule: form.autoSchedule,
      access_mode: form.accessMode,
      access_password: form.accessPassword,
    });

    if (!result.success) {
      setFieldErrors(extractErrors(result.error));
      return;
    }

    setFieldErrors({});
    onSubmit(channel.id, {
      name: form.name,
      description: form.description,
      timezone: form.timezone,
      schedule_config: { day_blocks: form.dayBlocks },
      rotation_policy: form.rotationPolicy,
      auto_schedule: form.autoSchedule,
      access_mode: form.accessMode,
      logo: form.logo,
      logo_position: form.logoPosition,
      logo_opacity: form.logoOpacity / 100,
      webhook_url: form.webhookUrl || null,
      ...(form.webhookUrl
        ? {
            webhook_poll_interval_secs:
              form.webhookPollInterval === "" ? 5 : form.webhookPollInterval,
          }
        : {}),
      webhook_body_template: form.webhookBodyTemplate || null,
      webhook_headers: form.webhookHeaders || null,
    });
  };


  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-[min(1100px,95vw)]"
      >
        <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 flex-1 overflow-hidden">
            {/* Left sidebar */}
            <div className="w-[300px] shrink-0 space-y-6 overflow-y-auto border-r border-zinc-800 px-5 py-4">
              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                  Basic info
                </h3>

                <Field label="Name" error={fieldErrors["name"]}>
                  <TextInput
                    required
                    value={form.name}
                    onChange={form.setName}
                    placeholder="90s Sitcom Network"
                    error={!!fieldErrors["name"]}
                  />
                </Field>

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

                <Field label="Description">
                  <textarea
                    value={form.description}
                    onChange={(e) => form.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>

                <label className="flex cursor-pointer items-center justify-between gap-3 rounded-md border border-zinc-700 bg-zinc-800/50 px-3 py-2.5">
                  <div>
                    <p className="text-sm text-zinc-200">Auto-generate schedule</p>
                    <p className="text-[11px] text-zinc-600">
                      Automatically regenerate when the schedule is about to expire
                    </p>
                  </div>
                  <button
                    type="button"
                    role="switch"
                    aria-checked={form.autoSchedule}
                    onClick={() => form.setAutoSchedule((v) => !v)}
                    className={`relative inline-flex h-5 w-9 shrink-0 rounded-full border-2 border-transparent transition-colors focus:outline-none ${form.autoSchedule ? "bg-zinc-300" : "bg-zinc-700"}`}
                  >
                    <span
                      className={`pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform ${form.autoSchedule ? "translate-x-4" : "translate-x-0"}`}
                    />
                  </button>
                </label>

                <Field label="Channel access">
                  <AccessSettingsEditor
                    accessMode={form.accessMode}
                    accessPassword={form.accessPassword}
                    onAccessModeChange={form.setAccessMode}
                    onAccessPasswordChange={form.setAccessPassword}
                    label="Access mode"
                    passwordLabel="Channel password"
                    passwordHint="Leave blank to keep existing password"
                  />
                </Field>
              </section>

              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                  Logo
                </h3>
                <LogoEditor
                  logo={form.logo}
                  logoPosition={form.logoPosition}
                  logoOpacity={form.logoOpacity}
                  onLogoChange={form.setLogo}
                  onPositionChange={form.setLogoPosition}
                  onOpacityChange={form.setLogoOpacity}
                />
              </section>

              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                  Rotation policy
                </h3>
                <RotationPolicyEditor
                  policy={form.rotationPolicy}
                  errors={fieldErrors}
                  onChange={form.setRotationPolicy}
                />
              </section>

              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">
                  Webhook
                </h3>
                <WebhookEditor
                  webhookUrl={form.webhookUrl}
                  webhookPollInterval={form.webhookPollInterval}
                  webhookFormat={form.webhookFormat}
                  webhookBodyTemplate={form.webhookBodyTemplate}
                  webhookHeaders={form.webhookHeaders}
                  onWebhookUrlChange={form.setWebhookUrl}
                  onWebhookPollIntervalChange={form.setWebhookPollInterval}
                  onWebhookFormatChange={form.setWebhookFormat}
                  onWebhookBodyTemplateChange={form.setWebhookBodyTemplate}
                  onWebhookHeadersChange={form.setWebhookHeaders}
                />
              </section>
            </div>

            {/* Right: block editor */}
            <div className="flex flex-1 flex-col overflow-hidden">
              {/* Day tab bar */}
              <div className="shrink-0 flex items-center border-b border-zinc-800 overflow-x-auto">
                {WEEKDAYS.map(day => (
                  <button
                    key={day}
                    type="button"
                    onClick={() => { setActiveDay(day); form.setSelectedBlockId(null); }}
                    className={cn(
                      'px-4 py-2.5 text-sm whitespace-nowrap transition-colors shrink-0',
                      activeDay === day
                        ? 'border-b-2 border-blue-400 text-blue-400'
                        : 'text-zinc-500 hover:text-zinc-300'
                    )}
                  >
                    {WEEKDAY_LABELS[day]}
                  </button>
                ))}
                {/* Copy-to control */}
                <div className="ml-auto flex items-center gap-1.5 px-3 py-1 text-xs text-zinc-500 shrink-0">
                  <span>Copy to</span>
                  <select
                    value={copyTarget}
                    onChange={e => setCopyTarget(e.target.value as Weekday | 'all' | '')}
                    className="bg-zinc-800 border border-zinc-700 rounded px-1 py-0.5 text-xs text-zinc-300"
                  >
                    <option value="">day…</option>
                    {WEEKDAYS.filter(d => d !== activeDay).map(d => (
                      <option key={d} value={d}>{WEEKDAY_LABELS[d]}</option>
                    ))}
                    <option value="all">All days</option>
                  </select>
                  <button
                    type="button"
                    onClick={handleCopyTo}
                    className="bg-blue-900/40 border border-blue-700 text-blue-400 px-2 py-0.5 rounded text-xs hover:bg-blue-900/60"
                  >
                    Copy
                  </button>
                </div>
              </div>

              <div className="shrink-0 space-y-3 border-b border-zinc-800 px-5 py-4">
                <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={() => form.addBlock(activeDay)}
                    className="border-zinc-700 text-zinc-300 hover:text-zinc-100"
                  >
                    <Plus className="size-3" />
                    Add block for {WEEKDAY_LABELS[activeDay]}
                  </Button>
                </div>

                <BlockTimeline
                  blocks={form.dayBlocks[activeDay] ?? []}
                  selectedId={form.selectedBlockId}
                  onSelect={form.setSelectedBlockId}
                  onChange={(blocks) => form.setDayBlocks(prev => ({ ...prev, [activeDay]: blocks }))}
                  onCreateBlock={(startMins, durationMins) =>
                    form.addBlock(activeDay, startMins, durationMins)
                  }
                />

                {(form.dayBlocks[activeDay] ?? []).length === 0 ? (
                  <p className="rounded-md border border-dashed border-zinc-700 px-4 py-4 text-center text-xs text-zinc-600">
                    No blocks for {WEEKDAY_LABELS[activeDay]}. Drag on the timeline or click Add block.
                  </p>
                ) : (
                  <div className="max-h-48 space-y-1 overflow-y-auto">
                    {(form.dayBlocks[activeDay] ?? []).map((block, idx) => (
                      <button
                        key={block.id}
                        type="button"
                        onClick={() => form.setSelectedBlockId(block.id)}
                        className={`flex w-full items-center gap-2 rounded-md px-3 py-2 text-left transition-colors ${
                          block.id === form.selectedBlockId
                            ? "border border-zinc-600 bg-zinc-700/60"
                            : "border border-transparent hover:bg-zinc-800/60"
                        }`}
                      >
                        <div
                          className="h-2.5 w-2.5 shrink-0 rounded-full"
                          style={{
                            backgroundColor:
                              BLOCK_COLORS[idx % BLOCK_COLORS.length],
                          }}
                        />
                        <span className="flex-1 truncate text-sm text-zinc-200">
                          {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>
                        <span
                          role="button"
                          onClick={(e) => {
                            e.stopPropagation();
                            form.removeBlock(activeDay, idx);
                          }}
                          className="rounded p-1 text-zinc-600 hover:bg-zinc-700 hover:text-red-400"
                        >
                          <Trash2 className="size-3.5" />
                        </span>
                      </button>
                    ))}
                  </div>
                )}
              </div>

              <div className="flex-1 overflow-y-auto px-5 py-4">
                {(() => {
                  if (form.selectedBlockId === null) {
                    return (
                      <div className="flex h-full items-center justify-center text-sm text-zinc-600">
                        Select a block or create one
                      </div>
                    );
                  }
                  const activeDayBlocks = form.dayBlocks[activeDay] ?? [];
                  const selectedIdx = activeDayBlocks.findIndex(
                    (b) => b.id === form.selectedBlockId,
                  );
                  const selectedBlock =
                    selectedIdx >= 0 ? activeDayBlocks[selectedIdx] : null;
                  if (!selectedBlock) {
                    return (
                      <div className="flex h-full items-center justify-center text-sm text-zinc-600">
                        Select a block or create one
                      </div>
                    );
                  }
                  return (
                    <BlockEditor
                      block={selectedBlock}
                      index={selectedIdx}
                      errors={fieldErrors}
                      providers={providers}
                      onChange={(b) => form.updateBlock(activeDay, selectedIdx, b)}
                    />
                  );
                })()}
              </div>
            </div>
          </div>

          <div className="flex items-center justify-between border-t border-zinc-800 px-6 py-4">
            {(error || Object.keys(fieldErrors).length > 0) && (
              <p className="text-xs text-red-400">
                {error ?? "Please fix the errors above"}
              </p>
            )}
            <div className="ml-auto flex gap-2">
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() => setConfigHistoryOpen(true)}
                className="border-zinc-700 text-zinc-400 hover:text-zinc-100"
              >
                Config history
              </Button>
              <Button
                type="button"
                variant="ghost"
                onClick={() => onOpenChange(false)}
                disabled={isPending}
              >
                Cancel
              </Button>
              <Button type="submit" disabled={isPending}>
                {isPending ? "Saving…" : "Save changes"}
              </Button>
            </div>
          </div>
          {channel && (
            <ConfigHistorySheet
              channelId={channel.id}
              open={configHistoryOpen}
              onOpenChange={setConfigHistoryOpen}
            />
          )}
        </form>
      </SheetContent>
    </Sheet>
  );
}
