import { useState, useCallback } from "react";
import { get, post } from "../../api/client";
import type {
  Project,
  FormFieldDescriptor,
  FormFieldGroup,
} from "../../api/types";
import { TagInput, type TagOption } from "../TagInput";
import { CategoryPicker } from "./CategoryPicker";
import { FileDropZone } from "./FileDropZone";
import { useFormDescriptor } from "../../hooks/useFormDescriptor";
import {
  useFileUpload,
  type PendingAttachment,
} from "../../hooks/useFileUpload";
import { useAuth } from "../../hooks/useAuth";

// Item-level field names that are sent as top-level API fields, not properties.
const ITEM_LEVEL_FIELDS = new Set([
  "item_type",
  "description",
  "sourcing_type",
  "long_description",
  "projects",
]);

interface CreateItemPaneProps {
  onCreated: (partNumber: string) => void;
  onCancel: () => void;
}

export function CreateItemPane({ onCreated, onCancel }: CreateItemPaneProps) {
  const { user } = useAuth();
  const { descriptor, categories } = useFormDescriptor();
  const { upload } = useFileUpload();

  // Single form state for all fields (item-level + properties).
  const [category, setCategory] = useState("");
  const [fields, setFields] = useState<Record<string, string>>({});
  const [selectedProjects, setSelectedProjects] = useState<string[]>([]);

  // Attachments.
  const [attachments, setAttachments] = useState<PendingAttachment[]>([]);
  const [thumbnailFile, setThumbnailFile] = useState<PendingAttachment | null>(
    null,
  );

  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const setField = (name: string, value: string) =>
    setFields((prev) => ({ ...prev, [name]: value }));

  const getField = (name: string) => fields[name] ?? "";

  // Derive item_type from category using derived_from_category mapping
  const deriveItemType = (cat: string): string => {
    if (!cat || !descriptor?.item_fields?.item_type?.derived_from_category) {
      return getField("item_type") || "part";
    }
    const mapping = descriptor.item_fields.item_type.derived_from_category;
    const prefix = cat[0]!;
    return mapping[prefix] ?? mapping["default"] ?? "part";
  };

  const handleCategoryChange = (cat: string) => {
    setCategory(cat);
    // Auto-derive item_type when category changes
    if (descriptor?.item_fields?.item_type?.derived_from_category) {
      const derived = cat
        ? (descriptor.item_fields.item_type.derived_from_category[cat[0]!] ??
          descriptor.item_fields.item_type.derived_from_category["default"] ??
          "part")
        : "part";
      setField("item_type", derived);
    }
  };

  const searchProjects = useCallback(
    async (query: string): Promise<TagOption[]> => {
      const all = await get<Project[]>("/api/projects");
      const q = query.toLowerCase();
      return all
        .filter(
          (p) =>
            !q ||
            p.code.toLowerCase().includes(q) ||
            (p.name ?? "").toLowerCase().includes(q),
        )
        .map((p) => ({
          id: p.code,
          label: p.code + (p.name ? " \u2014 " + p.name : ""),
        }));
    },
    [],
  );

  const handleFilesAdded = useCallback((files: PendingAttachment[]) => {
    setAttachments((prev) => [...prev, ...files]);
  }, []);

  const handleFileRemoved = useCallback((index: number) => {
    setAttachments((prev) => prev.filter((_, i) => i !== index));
  }, []);

  const handleThumbnailSelect = useCallback(() => {
    const input = document.createElement("input");
    input.type = "file";
    input.accept = ".png,.jpg,.jpeg,.webp";
    input.onchange = () => {
      const file = input.files?.[0];
      if (!file) return;

      setThumbnailFile({
        file,
        objectKey: "",
        uploadProgress: 0,
        uploadStatus: "pending",
      });
    };
    input.click();
  }, []);

  const handleSubmit = async () => {
    if (!category) {
      setError("Category is required");
      return;
    }
    setSaving(true);
    setError(null);

    // Split fields into item-level and properties
    const properties: Record<string, unknown> = {};
    for (const [k, v] of Object.entries(fields)) {
      if (!v) continue;
      if (ITEM_LEVEL_FIELDS.has(k)) continue; // handled separately
      // Coerce type from descriptor
      const fieldDef = findFieldDef(k);
      if (fieldDef?.type === "number") properties[k] = Number(v);
      else if (fieldDef?.type === "boolean") properties[k] = v === "true";
      else properties[k] = v;
    }

    try {
      const result = await post<{ part_number: string }>("/api/items", {
        schema: "kindred-rd",
        category,
        description: getField("description") || undefined,
        item_type: deriveItemType(category),
        projects: selectedProjects.length > 0 ? selectedProjects : undefined,
        properties: Object.keys(properties).length > 0 ? properties : undefined,
        sourcing_type: getField("sourcing_type") || undefined,
        long_description: getField("long_description") || undefined,
      });

      const pn = result.part_number;
      const encodedPN = encodeURIComponent(pn);

      // Upload attachments via direct multipart POST.
      for (const att of attachments) {
        try {
          await upload(att.file, `/api/items/${encodedPN}/files/upload`);
        } catch {
          // File upload failure is non-blocking.
        }
      }

      // Upload thumbnail via direct multipart POST.
      if (thumbnailFile) {
        try {
          await upload(
            thumbnailFile.file,
            `/api/items/${encodedPN}/thumbnail/upload`,
          );
        } catch {
          // Thumbnail failure is non-blocking.
        }
      }

      onCreated(pn);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to create item");
    } finally {
      setSaving(false);
    }
  };

  // Find field definition from descriptor (global groups + category groups).
  function findFieldDef(name: string): FormFieldDescriptor | undefined {
    if (descriptor?.field_groups) {
      for (const group of descriptor.field_groups) {
        const f = group.fields.find((fd) => fd.name === name);
        if (f) return f;
      }
    }
    if (descriptor?.category_field_groups && category) {
      const prefix = category[0]!;
      const catGroups = descriptor.category_field_groups[prefix];
      if (catGroups) {
        for (const group of catGroups) {
          const f = group.fields.find((fd) => fd.name === name);
          if (f) return f;
        }
      }
    }
    return undefined;
  }

  // Get category-specific field groups for the selected category.
  const catFieldGroups: FormFieldGroup[] =
    category && descriptor?.category_field_groups
      ? (descriptor.category_field_groups[category[0]!] ?? [])
      : [];

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      {/* Header */}
      <div style={headerStyle}>
        <span
          style={{
            color: "var(--ctp-green)",
            fontWeight: 600,
            fontSize: "var(--font-body)",
          }}
        >
          New Item
        </span>
        <span style={{ flex: 1 }} />
        <button
          onClick={() => void handleSubmit()}
          disabled={saving}
          style={{
            ...actionBtnStyle,
            backgroundColor: "var(--ctp-green)",
            opacity: saving ? 0.6 : 1,
          }}
        >
          {saving ? "Creating..." : "Create"}
        </button>
        <button onClick={onCancel} style={cancelBtnStyle}>
          Cancel
        </button>
      </div>

      {/* Two-column body */}
      <div
        style={{
          flex: 1,
          display: "grid",
          gridTemplateColumns: "1fr 280px",
          overflow: "hidden",
        }}
      >
        {/* Left: form */}
        <div style={{ overflow: "auto", padding: "0.75rem" }}>
          {error && <div style={errorStyle}>{error}</div>}

          {/* Category picker */}
          <SectionHeader>Category *</SectionHeader>
          <CategoryPicker
            value={category}
            onChange={handleCategoryChange}
            categories={categories}
            stages={descriptor?.category_picker?.stages}
          />

          {/* Dynamic field groups from descriptor */}
          {descriptor?.field_groups?.map((group) => (
            <div key={group.key}>
              <SectionHeader>{group.label}</SectionHeader>
              <div style={fieldGridStyle}>
                {group.fields.map((field) =>
                  renderField(
                    field,
                    getField(field.name),
                    (v) => setField(field.name, v),
                    selectedProjects,
                    setSelectedProjects,
                    searchProjects,
                  ),
                )}
              </div>
            </div>
          ))}

          {/* Category-specific field groups */}
          {catFieldGroups.map((group) => (
            <div key={group.key}>
              <SectionHeader>{group.label}</SectionHeader>
              <div style={fieldGridStyle}>
                {group.fields.map((field) =>
                  renderField(
                    field,
                    getField(field.name),
                    (v) => setField(field.name, v),
                    selectedProjects,
                    setSelectedProjects,
                    searchProjects,
                  ),
                )}
              </div>
            </div>
          ))}
        </div>

        {/* Right: sidebar */}
        <div
          style={{
            borderLeft: "1px solid var(--ctp-surface1)",
            overflow: "auto",
            padding: "0.75rem",
            display: "flex",
            flexDirection: "column",
            gap: "0.75rem",
          }}
        >
          {/* Metadata */}
          <SidebarSection title="Metadata">
            <MetaRow label="Revision" value="A" />
            <MetaRow
              label="Created By"
              value={user?.display_name ?? user?.username ?? "---"}
            />
          </SidebarSection>

          {/* Attachments */}
          <SidebarSection title="Attachments">
            <FileDropZone
              files={attachments}
              onFilesAdded={handleFilesAdded}
              onFileRemoved={handleFileRemoved}
              accept=".FCStd,.step,.stl,.pdf,.png,.jpg,.dxf"
            />
          </SidebarSection>

          {/* Thumbnail */}
          <SidebarSection title="Thumbnail">
            <div
              onClick={handleThumbnailSelect}
              style={{
                aspectRatio: "4/3",
                borderRadius: "0.5rem",
                border: "1px dashed var(--ctp-surface1)",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                cursor: "pointer",
                overflow: "hidden",
                backgroundColor: "var(--ctp-mantle)",
              }}
            >
              {thumbnailFile ? (
                <img
                  src={URL.createObjectURL(thumbnailFile.file)}
                  alt="Thumbnail preview"
                  style={{ width: "100%", height: "100%", objectFit: "cover" }}
                />
              ) : (
                <span
                  style={{
                    fontSize: "var(--font-table)",
                    color: "var(--ctp-subtext0)",
                  }}
                >
                  Click to select
                </span>
              )}
            </div>
          </SidebarSection>
        </div>
      </div>
    </div>
  );
}

// --- Field renderer ---

function renderField(
  field: FormFieldDescriptor,
  value: string,
  onChange: (v: string) => void,
  selectedProjects: string[],
  setSelectedProjects: (v: string[]) => void,
  searchProjects: (q: string) => Promise<{ id: string; label: string }[]>,
) {
  const widget =
    field.widget ?? (field.type === "boolean" ? "checkbox" : "text");

  // Projects field gets special tag_input treatment
  if (widget === "tag_input") {
    return (
      <div key={field.name} style={{ gridColumn: "1 / -1" }}>
        <FormGroup label={field.label}>
          <TagInput
            value={selectedProjects}
            onChange={setSelectedProjects}
            placeholder="Search projects\u2026"
            searchFn={searchProjects}
          />
        </FormGroup>
      </div>
    );
  }

  if (widget === "textarea") {
    return (
      <div key={field.name} style={{ gridColumn: "1 / -1" }}>
        <FormGroup label={field.label}>
          <textarea
            className="silo-input"
            value={value}
            onChange={(e) => onChange(e.target.value)}
            style={{ ...inputStyle, minHeight: 60, resize: "vertical" }}
            placeholder={field.description ?? ""}
          />
        </FormGroup>
      </div>
    );
  }

  if (widget === "select" && field.options) {
    return (
      <FormGroup key={field.name} label={field.label}>
        <select
          className="silo-input"
          value={value || (field.default != null ? String(field.default) : "")}
          onChange={(e) => onChange(e.target.value)}
          style={inputStyle}
        >
          {!field.required && <option value="">---</option>}
          {field.options.map((opt) => (
            <option key={opt} value={opt}>
              {opt}
            </option>
          ))}
        </select>
      </FormGroup>
    );
  }

  if (widget === "checkbox") {
    return (
      <FormGroup key={field.name} label={field.label}>
        <select
          className="silo-input"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={inputStyle}
        >
          <option value="">---</option>
          <option value="true">Yes</option>
          <option value="false">No</option>
        </select>
      </FormGroup>
    );
  }

  if (widget === "currency") {
    return (
      <FormGroup
        key={field.name}
        label={`${field.label}${field.currency ? ` (${field.currency})` : ""}`}
      >
        <input
          className="silo-input"
          type="number"
          step="0.01"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={inputStyle}
          placeholder="0.00"
        />
      </FormGroup>
    );
  }

  if (widget === "url") {
    return (
      <div key={field.name} style={{ gridColumn: "1 / -1" }}>
        <FormGroup label={field.label}>
          <input
            className="silo-input"
            type="url"
            value={value}
            onChange={(e) => onChange(e.target.value)}
            style={inputStyle}
            placeholder="https://..."
          />
        </FormGroup>
      </div>
    );
  }

  // Default: text or number input
  const inputType = field.type === "number" ? "number" : "text";
  const placeholder = field.unit
    ? `${field.description ?? ""} (${field.unit})`
    : (field.description ?? "");

  return (
    <FormGroup key={field.name} label={field.label}>
      <input
        className="silo-input"
        type={inputType}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        style={inputStyle}
        placeholder={placeholder}
      />
    </FormGroup>
  );
}

// --- Sub-components ---

function SectionHeader({ children }: { children: React.ReactNode }) {
  return (
    <div
      style={{
        display: "flex",
        alignItems: "center",
        gap: "0.5rem",
        margin: "0.75rem 0 0.5rem",
      }}
    >
      <span
        style={{
          fontSize: "var(--font-sm)",
          fontWeight: 600,
          textTransform: "uppercase",
          letterSpacing: "0.05em",
          color: "var(--ctp-subtext0)",
          whiteSpace: "nowrap",
        }}
      >
        {children}
      </span>
      <div
        style={{
          flex: 1,
          height: 1,
          backgroundColor: "var(--ctp-surface1)",
        }}
      />
    </div>
  );
}

function SidebarSection({
  title,
  children,
}: {
  title: string;
  children: React.ReactNode;
}) {
  return (
    <div
      style={{
        borderBottom: "1px solid var(--ctp-surface0)",
        paddingBottom: "0.75rem",
      }}
    >
      <div
        style={{
          fontSize: "var(--font-sm)",
          fontWeight: 600,
          textTransform: "uppercase",
          letterSpacing: "0.05em",
          color: "var(--ctp-subtext0)",
          marginBottom: "0.5rem",
        }}
      >
        {title}
      </div>
      {children}
    </div>
  );
}

function MetaRow({ label, value }: { label: string; value: string }) {
  return (
    <div
      style={{
        display: "flex",
        justifyContent: "space-between",
        fontSize: "var(--font-table)",
        padding: "0.25rem 0",
      }}
    >
      <span style={{ color: "var(--ctp-subtext0)" }}>{label}</span>
      <span style={{ color: "var(--ctp-text)" }}>{value}</span>
    </div>
  );
}

function FormGroup({
  label,
  children,
}: {
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div style={{ marginBottom: "0.5rem" }}>
      <label
        style={{
          display: "block",
          fontSize: "0.75rem",
          color: "var(--ctp-subtext0)",
          marginBottom: "0.25rem",
        }}
      >
        {label}
      </label>
      {children}
    </div>
  );
}

// --- Styles ---

const headerStyle: React.CSSProperties = {
  display: "flex",
  alignItems: "center",
  gap: "0.75rem",
  padding: "0.5rem 0.75rem",
  borderBottom: "1px solid var(--ctp-surface1)",
  backgroundColor: "var(--ctp-mantle)",
  flexShrink: 0,
};

const actionBtnStyle: React.CSSProperties = {
  padding: "0.25rem 0.75rem",
  fontSize: "0.75rem",
  fontWeight: 500,
  border: "none",
  borderRadius: "0.25rem",
  color: "var(--ctp-crust)",
  cursor: "pointer",
};

const cancelBtnStyle: React.CSSProperties = {
  background: "none",
  border: "none",
  cursor: "pointer",
  color: "var(--ctp-subtext1)",
  fontSize: "0.75rem",
  fontWeight: 500,
  padding: "0.25rem 0.5rem",
  borderRadius: "0.25rem",
};

const inputStyle: React.CSSProperties = {
  width: "100%",
  padding: "0.25rem 0.5rem",
  fontSize: "var(--font-body)",
  backgroundColor: "var(--ctp-base)",
  border: "1px solid var(--ctp-surface1)",
  borderRadius: "0.25rem",
  color: "var(--ctp-text)",
  boxSizing: "border-box",
};

const fieldGridStyle: React.CSSProperties = {
  display: "grid",
  gridTemplateColumns: "1fr 1fr",
  gap: "0 1rem",
};

const errorStyle: React.CSSProperties = {
  color: "var(--ctp-red)",
  backgroundColor: "rgba(243,139,168,0.1)",
  padding: "0.5rem",
  borderRadius: "0.25rem",
  marginBottom: "0.5rem",
  fontSize: "var(--font-body)",
};
