"use client";

import React, { ReactNode, CSSProperties, useRef, useState } from "react";
import { JM } from "./modal-theme";
import { STARTER_KITS } from "@/lib/design-kits/registry";
import type { StarterKitDefinition } from "@/lib/design-kits/types";
import { UI_FOUNDATION_LABELS } from "@/lib/design-kits/types";
import {
  PRODUCT_CATEGORIES,
  kitsOrderedForCategory,
  type ProductCategoryId,
} from "@/lib/design-kits/product-categories";
import { DesignKitPreviewPane } from "./design-kit-preview-pane";

export interface SetupProps {
  workspace: string;
  onClose: () => void;
  onBack: () => void;
}

export function FieldLabel({ children }: { children: ReactNode }) {
  return (
    <label style={{
      display: "block", fontSize: 12, fontWeight: 600, color: JM.mid,
      marginBottom: 6, fontFamily: JM.fontSans,
    }}>
      {children}
    </label>
  );
}

/** Audience picker — drives default infra (auth, payments, email, domain).
 *  - "team"      → internal users (your team / employees). SSO-style auth,
 *                  no payments by default, simple roles.
 *  - "customers" → external users (the public). Public sign-up, payments
 *                  on by default, transactional email, custom domain.
 *  Either choice can be changed later from the Infrastructure tab. */
export type Audience = "team" | "customers";

export function ProductCategorySelector({
  value,
  onChange,
}: {
  value: ProductCategoryId;
  onChange: (v: ProductCategoryId) => void;
}) {
  return (
    <div style={{ marginBottom: 22 }}>
      <FieldLabel>What are you building?</FieldLabel>
      <p
        style={{
          fontSize: 11,
          color: JM.muted,
          marginTop: -2,
          marginBottom: 10,
          lineHeight: 1.45,
          fontFamily: JM.fontSans,
        }}
      >
        Choose a product shape — we&apos;ll suggest matching design starters on the next step.
      </p>
      <div
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
          gap: 8,
        }}
      >
        {PRODUCT_CATEGORIES.map((c) => {
          const sel = c.id === value;
          return (
            <button
              key={c.id}
              type="button"
              onClick={() => onChange(c.id)}
              style={{
                display: "flex",
                flexDirection: "column",
                alignItems: "flex-start",
                gap: 6,
                padding: "10px 11px",
                minHeight: 76,
                borderRadius: 9,
                border: `1px solid ${sel ? JM.indigo : JM.border}`,
                background: sel ? JM.cream : JM.inputBg,
                cursor: "pointer",
                textAlign: "left",
                fontFamily: JM.fontSans,
                transition: "all 0.15s",
                boxShadow: sel ? "0 0 0 1px rgba(99,102,241,0.2)" : undefined,
                boxSizing: "border-box",
              }}
            >
              <span
                style={{
                  width: 7,
                  height: 7,
                  borderRadius: 999,
                  background: sel ? JM.indigo : "#d4d4d8",
                  flexShrink: 0,
                }}
              />
              <span style={{ display: "flex", flexDirection: "column", gap: 3, minWidth: 0 }}>
                <span style={{ fontSize: 12, fontWeight: 600, color: JM.ink, lineHeight: 1.25 }}>
                  {c.label}
                </span>
                <span
                  style={{
                    fontSize: 10,
                    color: JM.muted,
                    lineHeight: 1.35,
                    display: "-webkit-box",
                    WebkitLineClamp: 2,
                    WebkitBoxOrient: "vertical" as const,
                    overflow: "hidden",
                  }}
                >
                  {c.hint}
                </span>
              </span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

/** Split layout: starter kits (filtered by product category) + live preview pane. */
export function DesignKitSplitSelector({
  productCategory,
  value,
  onChange,
}: {
  productCategory: ProductCategoryId;
  value: string;
  onChange: (kitId: string) => void;
}) {
  const order = kitsOrderedForCategory(productCategory);
  const kits = order
    .map((id) => STARTER_KITS.find((k) => k.id === id))
    .filter(Boolean) as StarterKitDefinition[];
  const selected = kits.find((k) => k.id === value) ?? kits[0];

  return (
    <div style={{ marginBottom: 12 }}>
      <FieldLabel>Design system</FieldLabel>
      <p
        style={{
          fontSize: 11,
          color: JM.muted,
          marginTop: -2,
          marginBottom: 12,
          lineHeight: 1.45,
          fontFamily: JM.fontSans,
        }}
      >
        Pick a starter look — preview updates as you click. You can customize tokens anytime in the Design tab.
      </p>
      <div
        style={{
          display: "flex",
          flexDirection: "row",
          alignItems: "stretch",
          gap: 18,
          flexWrap: "wrap",
        }}
      >
        <div
          style={{
            width: 288,
            flexShrink: 0,
            maxHeight: 420,
            overflowY: "auto",
            paddingRight: 6,
            display: "flex",
            flexDirection: "column",
            gap: 8,
          }}
        >
          {kits.map((k) => {
            const sel = value === k.id;
            const dot = k.defaults.accentHex ?? "#6366f1";
            return (
              <button
                key={k.id}
                type="button"
                onClick={() => onChange(k.id)}
                style={{
                  textAlign: "left",
                  padding: "11px 12px",
                  borderRadius: 9,
                  border: `1px solid ${sel ? JM.indigo : JM.border}`,
                  background: sel ? JM.cream : JM.inputBg,
                  cursor: "pointer",
                  fontFamily: JM.fontSans,
                  transition: "all 0.15s",
                  boxShadow: sel ? "0 0 0 1px rgba(99,102,241,0.2)" : undefined,
                  flexShrink: 0,
                }}
              >
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 5 }}>
                  <span
                    style={{
                      width: 11,
                      height: 11,
                      borderRadius: 999,
                      background: dot,
                      flexShrink: 0,
                      border: "1px solid rgba(0,0,0,0.08)",
                    }}
                  />
                  <span style={{ fontSize: 12.5, fontWeight: 600, color: JM.ink }}>{k.name}</span>
                </div>
                <div style={{ fontSize: 10.5, color: JM.muted, lineHeight: 1.35 }}>{k.tagline}</div>
                <div style={{ fontSize: 10, color: "#94a3b8", marginTop: 4, lineHeight: 1.3 }}>
                  {UI_FOUNDATION_LABELS[k.uiFoundation]}
                </div>
              </button>
            );
          })}
        </div>
        <div
          style={{
            flex: "1 1 280px",
            minWidth: 280,
            minHeight: 308,
            borderRadius: 12,
            padding: 12,
            background: JM.cream,
            border: `1px solid ${JM.border}`,
            boxSizing: "border-box",
          }}
        >
          {selected ? <DesignKitPreviewPane kit={selected} /> : null}
        </div>
      </div>
    </div>
  );
}

/** Starter design system picker — persisted as `fs_projects.data.designKit` on create. */
export function DesignKitSelector({
  value,
  onChange,
}: {
  value: string;
  onChange: (kitId: string) => void;
}) {
  return (
    <div style={{ marginBottom: 22 }}>
      <FieldLabel>Design system</FieldLabel>
      <p style={{
        fontSize: 11,
        color: JM.muted,
        marginTop: -2,
        marginBottom: 10,
        lineHeight: 1.45,
        fontFamily: JM.fontSans,
      }}>
        Pick a starter look for your UI. Vibn uses this when building and when you open the Design tab — you can customize tokens anytime.
      </p>
      <div style={{
        display: "grid",
        gridTemplateColumns: "1fr 1fr",
        gap: 8,
        maxHeight: 280,
        overflowY: "auto",
        paddingRight: 4,
      }}>
        {STARTER_KITS.map((k) => {
          const sel = value === k.id;
          const dot = k.defaults.accentHex ?? "#6366f1";
          return (
            <button
              key={k.id}
              type="button"
              onClick={() => onChange(k.id)}
              style={{
                textAlign: "left",
                padding: "12px 12px",
                borderRadius: 9,
                border: `1px solid ${sel ? JM.indigo : JM.border}`,
                background: sel ? JM.cream : JM.inputBg,
                cursor: "pointer",
                fontFamily: JM.fontSans,
                transition: "all 0.15s",
                boxShadow: sel ? "0 0 0 1px rgba(99,102,241,0.2)" : undefined,
              }}
            >
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
                <span style={{
                  width: 12,
                  height: 12,
                  borderRadius: 999,
                  background: dot,
                  flexShrink: 0,
                  border: "1px solid rgba(0,0,0,0.08)",
                }} />
                <span style={{ fontSize: 12.5, fontWeight: 600, color: JM.ink }}>{k.name}</span>
              </div>
              <div style={{ fontSize: 10.5, color: JM.muted, lineHeight: 1.35 }}>{k.tagline}</div>
              <div style={{ fontSize: 10, color: "#94a3b8", marginTop: 4, lineHeight: 1.3 }}>
                {UI_FOUNDATION_LABELS[k.uiFoundation]}
              </div>
            </button>
          );
        })}
      </div>
    </div>
  );
}

export function AudienceSelector({
  value,
  onChange,
}: {
  value: Audience;
  onChange: (v: Audience) => void;
}) {
  const cardBase: CSSProperties = {
    flex: "0 0 auto",
    width: 148,
    border: `1px solid ${JM.border}`,
    borderRadius: 8,
    padding: "8px 10px",
    cursor: "pointer",
    textAlign: "center" as const,
    background: JM.inputBg,
    transition: "all 0.15s",
    fontFamily: JM.fontSans,
    minHeight: 0,
  };

  const row = (key: Audience, emoji: string, title: string, sub: string) => {
    const sel = value === key;
    return (
      <button
        type="button"
        key={key}
        onClick={() => onChange(key)}
        style={{
          ...cardBase,
          borderColor: sel ? JM.indigo : JM.border,
          background: sel ? JM.cream : JM.inputBg,
          boxShadow: sel ? "0 0 0 1px rgba(99,102,241,0.2)" : undefined,
        }}
      >
        <div style={{ fontSize: 15, lineHeight: 1, marginBottom: 4 }}>{emoji}</div>
        <div style={{ fontSize: 11, fontWeight: 600, color: JM.ink, lineHeight: 1.25 }}>{title}</div>
        <div style={{ fontSize: 9.5, color: JM.muted, marginTop: 2, lineHeight: 1.35 }}>{sub}</div>
      </button>
    );
  };

  return (
    <div style={{ marginBottom: 22 }}>
      <FieldLabel>Who will use this?</FieldLabel>
      <div style={{ display: "flex", gap: 6, alignItems: "stretch", flexWrap: "wrap" }}>
        {row("team", "🏢", "My team", "Internal tool")}
        {row("customers", "🌍", "Customers", "Public product")}
      </div>
      <p style={{ fontSize: 11, color: JM.muted, marginTop: 7, lineHeight: 1.45 }}>
        We&apos;ll set up the right defaults (sign-up, payments, email). You can change this later.
      </p>
    </div>
  );
}

export type SeedDocumentPayload = {
  fileName: string;
  kind: "markdown" | "pdf";
  text?: string;
  base64?: string;
};

const MAX_MARKDOWN_CHARS = 200_000;
const MAX_PDF_BYTES = 4 * 1024 * 1024;

function readFileAsText(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => resolve(typeof r.result === "string" ? r.result : "");
    r.onerror = () => reject(r.error ?? new Error("read failed"));
    r.readAsText(file);
  });
}

function readFileAsDataUrl(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => resolve(typeof r.result === "string" ? r.result : "");
    r.onerror = () => reject(r.error ?? new Error("read failed"));
    r.readAsDataURL(file);
  });
}

/** Optional Markdown / PDF seed for the build wizard last step. */
export function SeedDocumentUpload({
  value,
  onChange,
}: {
  value: SeedDocumentPayload | null;
  onChange: (v: SeedDocumentPayload | null) => void;
}) {
  const inputRef = useRef<HTMLInputElement>(null);
  const [pickErr, setPickErr] = useState<string | null>(null);

  const handlePick = () => {
    setPickErr(null);
    inputRef.current?.click();
  };

  const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const list = e.target.files;
    e.target.value = "";
    const file = list?.[0];
    if (!file) return;
    const lower = file.name.toLowerCase();
    setPickErr(null);
    try {
      if (lower.endsWith(".md") || lower.endsWith(".markdown")) {
        let text = await readFileAsText(file);
        if (text.length > MAX_MARKDOWN_CHARS) text = text.slice(0, MAX_MARKDOWN_CHARS);
        onChange({ fileName: file.name, kind: "markdown", text });
        return;
      }
      if (lower.endsWith(".pdf")) {
        if (file.size > MAX_PDF_BYTES) {
          setPickErr("PDF must be 4MB or smaller.");
          return;
        }
        const dataUrl = await readFileAsDataUrl(file);
        const comma = dataUrl.indexOf(",");
        const base64 = comma >= 0 ? dataUrl.slice(comma + 1) : "";
        if (!base64) {
          setPickErr("Could not read PDF.");
          return;
        }
        onChange({ fileName: file.name, kind: "pdf", base64 });
        return;
      }
      setPickErr("Please choose a .md, .markdown, or .pdf file.");
    } catch {
      setPickErr("Could not read that file.");
    }
  };

  return (
    <div style={{ marginBottom: 14 }}>
      <FieldLabel>Supporting document</FieldLabel>
      <input
        ref={inputRef}
        type="file"
        accept=".md,.markdown,.pdf,application/pdf,text/markdown,text/plain"
        style={{ display: "none" }}
        onChange={handleChange}
      />
      <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
        <button
          type="button"
          onClick={handlePick}
          style={{
            padding: "8px 12px",
            borderRadius: 8,
            border: `1px solid ${JM.border}`,
            background: JM.inputBg,
            fontSize: 12,
            fontWeight: 600,
            color: JM.mid,
            cursor: "pointer",
            fontFamily: JM.fontSans,
          }}
        >
          {value ? "Replace document" : "Upload Markdown or PDF"}
        </button>
        {value ? (
          <span style={{ fontSize: 11, color: JM.ink, fontFamily: JM.fontSans }}>
            <span style={{ fontWeight: 600 }}>{value.fileName}</span>
            <span style={{ color: JM.muted }}> ({value.kind === "pdf" ? "PDF" : "Markdown"})</span>
            <button
              type="button"
              onClick={() => {
                onChange(null);
                setPickErr(null);
              }}
              style={{
                marginLeft: 10,
                border: "none",
                background: "none",
                color: JM.indigo,
                cursor: "pointer",
                fontSize: 11,
                fontWeight: 600,
                fontFamily: JM.fontSans,
              }}
            >
              Remove
            </button>
          </span>
        ) : (
          <span style={{ fontSize: 11, color: JM.muted, fontFamily: JM.fontSans }}>
            Optional — specs, notes, or briefs (.md / .pdf, PDF max 4MB)
          </span>
        )}
      </div>
      {pickErr ? (
        <p
          style={{
            fontSize: 11,
            color: "#b91c1c",
            marginTop: 8,
            marginBottom: 0,
            fontFamily: JM.fontSans,
          }}
        >
          {pickErr}
        </p>
      ) : null}
    </div>
  );
}

export function SetupHeader({
  icon,
  label,
  tagline,
  accent,
  onBack,
  onClose,
}: {
  icon: string;
  label: string;
  tagline: string;
  accent: string;
  onBack: () => void;
  onClose: () => void;
}) {
  return (
    <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", marginBottom: 22 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
        <button
          type="button"
          onClick={onBack}
          style={{
            background: "none", border: "none", cursor: "pointer",
            color: JM.muted, fontSize: "1rem", padding: "3px 5px",
            borderRadius: 4, lineHeight: 1, flexShrink: 0,
            fontFamily: JM.fontSans,
          }}
          onMouseEnter={e => (e.currentTarget.style.color = JM.ink)}
          onMouseLeave={e => (e.currentTarget.style.color = JM.muted)}
        >
          ←
        </button>
        <div>
          <h2 style={{
            fontFamily: JM.fontDisplay, fontSize: 18, fontWeight: 700,
            color: JM.ink, margin: 0, marginBottom: 3, letterSpacing: "-0.02em",
            display: "flex", alignItems: "center", gap: 8,
          }}>
            <span aria-hidden style={{ fontSize: 17, lineHeight: 1, opacity: 0.92 }}>{icon}</span>
            <span>{label}</span>
          </h2>
          <p style={{
            fontSize: 10.5, fontWeight: 600, color: accent, textTransform: "uppercase",
            letterSpacing: "0.07em", margin: 0, fontFamily: JM.fontSans,
          }}>
            {tagline}
          </p>
        </div>
      </div>
      <button
        type="button"
        onClick={onClose}
        style={{
          background: "none", border: "none", cursor: "pointer",
          color: JM.muted, fontSize: 20, lineHeight: 1,
          padding: 4, flexShrink: 0, fontFamily: JM.fontSans,
        }}
        onMouseEnter={e => (e.currentTarget.style.color = JM.mid)}
        onMouseLeave={e => (e.currentTarget.style.color = JM.muted)}
      >
        ×
      </button>
    </div>
  );
}

export function TextInput({
  value,
  onChange,
  placeholder,
  onKeyDown,
  autoFocus,
  inputRef,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  autoFocus?: boolean;
  inputRef?: React.RefObject<HTMLInputElement | null> | React.RefObject<HTMLInputElement>;
}) {
  const base: CSSProperties = {
    width: "100%", padding: "10px 13px", marginBottom: 16,
    borderRadius: 8, border: `1px solid ${JM.border}`,
    background: JM.inputBg, fontSize: 14,
    fontFamily: JM.fontSans, color: JM.ink,
    outline: "none", boxSizing: "border-box",
  };
  return (
    <input
      ref={inputRef}
      type="text"
      value={value}
      onChange={e => onChange(e.target.value)}
      onKeyDown={onKeyDown}
      placeholder={placeholder}
      autoFocus={autoFocus}
      style={base}
      onFocus={e => (e.currentTarget.style.borderColor = JM.indigo)}
      onBlur={e => (e.currentTarget.style.borderColor = JM.border)}
    />
  );
}

export function TextArea({
  value,
  onChange,
  placeholder,
  rows = 5,
  autoFocus,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  rows?: number;
  autoFocus?: boolean;
}) {
  return (
    <textarea
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      autoFocus={autoFocus}
      style={{
        width: "100%", padding: "11px 13px", marginBottom: 16,
        borderRadius: 8, border: `1px solid ${JM.border}`,
        background: JM.inputBg, fontSize: 14,
        fontFamily: JM.fontSans, color: JM.ink,
        outline: "none", boxSizing: "border-box",
        resize: "vertical", lineHeight: 1.5,
        minHeight: 96,
      }}
      onFocus={e => (e.currentTarget.style.borderColor = JM.indigo)}
      onBlur={e => (e.currentTarget.style.borderColor = JM.border)}
    />
  );
}

/** Page indicator dots for a multi-step setup screen. */
export function StepDots({ step, total }: { step: number; total: number }) {
  return (
    <div style={{ display: "flex", gap: 5, alignItems: "center" }}>
      {Array.from({ length: total }).map((_, i) => (
        <span
          key={i}
          style={{
            width: i === step ? 18 : 6, height: 6, borderRadius: 3,
            background: i === step ? JM.indigo : JM.border,
            transition: "all 0.2s",
          }}
        />
      ))}
    </div>
  );
}

/** Inline tab selector — used inside OSS setup to pick paste-link vs describe-it. */
export function SegmentedTabs<T extends string>({
  value, onChange, options,
}: {
  value: T;
  onChange: (v: T) => void;
  options: { id: T; label: string }[];
}) {
  return (
    <div style={{
      display: "flex", padding: 3, marginBottom: 14,
      background: JM.inputBg, border: `1px solid ${JM.border}`,
      borderRadius: 9, gap: 3,
    }}>
      {options.map(opt => {
        const sel = opt.id === value;
        return (
          <button
            key={opt.id}
            type="button"
            onClick={() => onChange(opt.id)}
            style={{
              flex: 1, padding: "7px 10px", borderRadius: 6,
              border: "none", cursor: "pointer",
              background: sel ? "#fff" : "transparent",
              color: sel ? JM.ink : JM.mid,
              fontSize: 12.5, fontWeight: sel ? 600 : 500,
              fontFamily: JM.fontSans,
              boxShadow: sel ? "0 1px 3px rgba(0,0,0,0.06)" : "none",
              transition: "all 0.15s",
            }}
          >
            {opt.label}
          </button>
        );
      })}
    </div>
  );
}

export function SecondaryButton({
  onClick, children,
}: { onClick: () => void; children: ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      style={{
        padding: "11px 16px", borderRadius: 8,
        border: `1px solid ${JM.border}`, background: "#fff",
        color: JM.mid, fontSize: 13.5, fontWeight: 600,
        fontFamily: JM.fontSans, cursor: "pointer",
        transition: "border-color 0.15s, color 0.15s",
      }}
      onMouseEnter={e => { e.currentTarget.style.borderColor = JM.mid; e.currentTarget.style.color = JM.ink; }}
      onMouseLeave={e => { e.currentTarget.style.borderColor = JM.border; e.currentTarget.style.color = JM.mid; }}
    >
      {children}
    </button>
  );
}

export function PrimaryButton({
  onClick,
  disabled,
  loading,
  children,
}: {
  onClick: () => void;
  disabled?: boolean;
  loading?: boolean;
  children: ReactNode;
}) {
  const active = !disabled && !loading;
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={!active}
      style={{
        width: "100%", padding: "12px",
        borderRadius: 8, border: "none",
        background: active ? JM.primaryGradient : "#E5E7EB",
        color: active ? "#fff" : JM.muted,
        fontSize: 14, fontWeight: 600,
        fontFamily: JM.fontSans,
        cursor: active ? "pointer" : "not-allowed",
        display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
        boxShadow: active ? JM.primaryShadow : "none",
        transition: "box-shadow 0.2s, transform 0.15s, opacity 0.15s",
      }}
      onMouseEnter={e => {
        if (active) {
          e.currentTarget.style.boxShadow = JM.primaryShadowHover;
          e.currentTarget.style.transform = "translateY(-1px)";
        }
      }}
      onMouseLeave={e => {
        e.currentTarget.style.boxShadow = active ? JM.primaryShadow : "none";
        e.currentTarget.style.transform = "none";
      }}
    >
      {loading ? (
        <>
          <span style={{
            width: 14, height: 14, borderRadius: "50%",
            border: "2px solid rgba(255,255,255,0.35)", borderTopColor: "#fff",
            animation: "vibn-spin 0.7s linear infinite", display: "inline-block",
          }} />
          Creating…
        </>
      ) : (
        children
      )}
    </button>
  );
}
