"use client";

import * as React from "react";
import {
  ExternalLink,
  FileIcon,
  Link2,
  User,
  X,
} from "lucide-react";

import { cn } from "@/lib/utils";
import {
  Avatar,
  AvatarFallback,
  AvatarImage,
} from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";

export type PropertyFieldType =
  | "text"
  | "richtext"
  | "number"
  | "date"
  | "select"
  | "multiselect"
  | "person"
  | "relation"
  | "url"
  | "file"
  | "checkbox";

export interface PropertyDefinitionInput {
  name: string;
  fieldType: PropertyFieldType;
  config?: {
    options?: { label: string; value: string }[];
    [key: string]: unknown;
  } | null;
}

export interface PropertyEditorProps {
  definition: PropertyDefinitionInput;
  value: unknown;
  onChange: (value: unknown) => void;
  className?: string;
}

function initials(name: string) {
  return name
    .split(/\s+/)
    .map((p) => p[0])
    .join("")
    .slice(0, 2)
    .toUpperCase();
}

export function PropertyEditor({
  definition,
  value,
  onChange,
  className,
}: PropertyEditorProps) {
  const { name, fieldType, config } = definition;
  const options = config?.options ?? [];

  const row = (control: React.ReactNode) => (
    <div
      className={cn(
        "grid grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)] items-center gap-2 py-1.5",
        className,
      )}
    >
      <label className="truncate text-xs font-medium text-muted-foreground">
        {name}
      </label>
      <div className="min-w-0">{control}</div>
    </div>
  );

  switch (fieldType) {
    case "text":
      return row(
        <Input
          value={String(value ?? "")}
          onChange={(e) => onChange(e.target.value)}
          className="h-8 text-xs"
        />,
      );

    case "richtext":
      return row(
        <textarea
          value={String(value ?? "")}
          onChange={(e) => onChange(e.target.value)}
          rows={3}
          className="flex min-h-[72px] w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 text-xs ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
          placeholder="Rich text (TipTap later)"
        />,
      );

    case "number": {
      const n =
        value === null || value === undefined || value === ""
          ? ""
          : Number(value);
      return row(
        <Input
          type="number"
          value={Number.isFinite(n as number) ? String(n) : ""}
          onChange={(e) => {
            const v = e.target.value;
            onChange(v === "" ? null : Number(v));
          }}
          className="h-8 text-xs"
        />,
      );
    }

    case "date":
      return row(
        <Input
          type="date"
          value={String(value ?? "").slice(0, 10)}
          onChange={(e) => onChange(e.target.value || null)}
          className="h-8 text-xs"
        />,
      );

    case "select": {
      const current = String(value ?? "");
      const label =
        options.find((o) => o.value === current)?.label ??
        (current || "—");
      return row(
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              variant="outline"
              size="sm"
              className="h-8 w-full justify-between px-2 text-xs font-normal"
            >
              <span className="truncate">{label}</span>
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="start" className="w-[var(--radix-dropdown-menu-trigger-width)]">
            {options.map((opt) => (
              <DropdownMenuItem
                key={opt.value}
                className="text-xs"
                onClick={() => onChange(opt.value)}
              >
                {opt.label}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>,
      );
    }

    case "multiselect": {
      const arr = Array.isArray(value)
        ? (value as string[])
        : value
          ? [String(value)]
          : [];
      const toggle = (v: string) => {
        if (arr.includes(v)) onChange(arr.filter((x) => x !== v));
        else onChange([...arr, v]);
      };
      return row(
        <div className="flex flex-wrap gap-1">
          {arr.map((v) => (
            <Badge
              key={v}
              variant="secondary"
              className="gap-0.5 pr-1 text-[10px] font-normal"
            >
              {options.find((o) => o.value === v)?.label ?? v}
              <button
                type="button"
                className="ml-0.5 rounded p-0.5 hover:bg-muted"
                onClick={() => toggle(v)}
                aria-label={`Remove ${v}`}
              >
                <X className="size-3" />
              </button>
            </Badge>
          ))}
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="sm" className="h-6 px-2 text-[10px]">
                + Add
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start" className="max-h-48 overflow-y-auto">
              {options.map((opt) => (
                <DropdownMenuItem
                  key={opt.value}
                  className="text-xs"
                  onClick={() => toggle(opt.value)}
                >
                  {opt.label}
                  {arr.includes(opt.value) ? " ✓" : ""}
                </DropdownMenuItem>
              ))}
            </DropdownMenuContent>
          </DropdownMenu>
        </div>,
      );
    }

    case "person": {
      const raw = value as
        | { user?: { name?: string; avatarUrl?: string | null } }
        | { name?: string; avatarUrl?: string | null }
        | null
        | undefined;
      const person =
        raw && typeof raw === "object" && "user" in raw && raw.user
          ? raw.user
          : (raw as { name?: string; avatarUrl?: string | null } | undefined);
      const displayName = person?.name ?? "Unassigned";
      return row(
        <div className="flex items-center gap-2">
          <Avatar className="size-7 border border-border">
            <AvatarImage src={person?.avatarUrl ?? undefined} alt="" />
            <AvatarFallback className="text-[10px] font-medium">
              {displayName === "Unassigned" ? (
                <User className="size-3.5 opacity-70" />
              ) : (
                initials(displayName)
              )}
            </AvatarFallback>
          </Avatar>
          <span className="truncate text-xs">{displayName}</span>
        </div>,
      );
    }

    case "relation": {
      const rel = value as
        | { id?: string; title?: string }
        | string
        | null
        | undefined;
      const title =
        typeof rel === "object" && rel && "title" in rel
          ? String(rel.title)
          : typeof rel === "string"
            ? rel
            : "—";
      return row(
        <Button
          variant="link"
          className="h-auto min-h-0 justify-start p-0 text-xs text-primary"
          type="button"
        >
          <Link2 className="mr-1 size-3.5 shrink-0" />
          <span className="truncate">{title}</span>
        </Button>,
      );
    }

    case "url":
      return row(
        <div className="relative">
          <ExternalLink className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
          <Input
            type="url"
            value={String(value ?? "")}
            onChange={(e) => onChange(e.target.value)}
            className="h-8 pl-8 text-xs"
            placeholder="https://"
          />
        </div>,
      );

    case "file":
      return row(
        <div className="flex items-center gap-2 text-xs text-muted-foreground">
          <FileIcon className="size-3.5 shrink-0" />
          <span className="truncate">{String(value ?? "No file")}</span>
        </div>,
      );

    case "checkbox":
      return row(
        <label className="flex cursor-pointer items-center gap-2">
          <input
            type="checkbox"
            checked={Boolean(value)}
            onChange={(e) => onChange(e.target.checked)}
            className={cn(
              "size-4 rounded border border-input bg-background",
              "text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
            )}
          />
          <span className="text-xs text-muted-foreground">
            {Boolean(value) ? "Yes" : "No"}
          </span>
        </label>,
      );

    default:
      return row(
        <Input
          value={String(value ?? "")}
          onChange={(e) => onChange(e.target.value)}
          className="h-8 text-xs"
        />,
      );
  }
}
