import { clsx } from "clsx";
import { formatDateLong } from "~/lib/format.js";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";

interface Props {
  fieldDefs: BlueprintFieldDefinition[];
  values: Record<string, unknown>;
  className?: string;
}

function renderValue(fieldDef: BlueprintFieldDefinition, value: unknown): React.ReactNode {
  if (value === null || value === undefined || value === "") {
    return <span className="text-gray-400">—</span>;
  }

  switch (fieldDef.type) {
    case FieldType.TEXT:
    case FieldType.TEXTAREA:
    case FieldType.URL:
    case FieldType.EMAIL:
      return <span className="text-gray-900">{String(value)}</span>;

    case FieldType.NUMBER:
      return (
        <span className="text-gray-900">
          {typeof value === "number" ? value.toLocaleString() : String(value)}
        </span>
      );

    case FieldType.BOOLEAN: {
      const bool = value === true || value === "true" || value === 1;
      return (
        <span
          className={clsx(
            "inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium",
            bool ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-500",
          )}
        >
          {bool ? "Yes" : "No"}
        </span>
      );
    }

    case FieldType.DATE: {
      const dateStr = String(value);
      const parsed = new Date(dateStr);
      if (isNaN(parsed.getTime())) {
        return <span className="text-gray-900">{dateStr}</span>;
      }
      return <span className="text-gray-900">{formatDateLong(parsed)}</span>;
    }

    case FieldType.SELECT: {
      const strVal = String(value);
      const option = fieldDef.options?.find((o) => o.value === strVal);
      return <span className="text-gray-900">{option?.label ?? strVal}</span>;
    }

    case FieldType.MULTI_SELECT: {
      const rawVals = Array.isArray(value) ? value : [value];
      const strVals = rawVals.map((v) => String(v)).filter(Boolean);

      if (strVals.length === 0) {
        return <span className="text-gray-400">—</span>;
      }

      const labels = strVals.map((v) => {
        const option = fieldDef.options?.find((o) => o.value === v);
        return { value: v, label: option?.label ?? v, color: option?.color };
      });

      return (
        <div className="flex flex-wrap gap-1">
          {labels.map(({ value: v, label }) => (
            <span
              key={v}
              className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-brand-50 text-brand-700"
            >
              {label}
            </span>
          ))}
        </div>
      );
    }

    default:
      return <span className="text-gray-900">{String(value)}</span>;
  }
}

function FieldRow({ fieldDef, value }: { fieldDef: BlueprintFieldDefinition; value: unknown }) {
  return (
    <div className="flex flex-col gap-0.5">
      <dt className="text-xs font-medium text-gray-500 uppercase tracking-wider">
        {fieldDef.label}
      </dt>
      <dd className="text-sm">{renderValue(fieldDef, value)}</dd>
      {fieldDef.description && <p className="text-xs text-gray-400">{fieldDef.description}</p>}
    </div>
  );
}

export function DynamicFieldRenderer({ fieldDefs, values, className }: Props) {
  const sorted = [...fieldDefs].sort((a, b) => a.order - b.order);

  // Separate grouped and ungrouped fields
  const ungrouped = sorted.filter((f) => !f.group);
  const groupMap = new Map<string, BlueprintFieldDefinition[]>();

  for (const field of sorted) {
    if (!field.group) continue;
    const existing = groupMap.get(field.group) ?? [];
    existing.push(field);
    groupMap.set(field.group, existing);
  }

  if (sorted.length === 0) {
    return null;
  }

  return (
    <div className={clsx("space-y-6", className)}>
      {ungrouped.length > 0 && (
        <dl className="grid grid-cols-1 sm:grid-cols-2 gap-4">
          {ungrouped.map((field) => (
            <FieldRow key={field.id} fieldDef={field} value={values[field.key]} />
          ))}
        </dl>
      )}

      {[...groupMap.entries()].map(([group, fields]) => (
        <div key={group} className="space-y-3">
          <h4 className="text-sm font-semibold text-gray-700 border-b border-gray-200 pb-1">
            {group}
          </h4>
          <dl className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            {fields.map((field) => (
              <FieldRow key={field.id} fieldDef={field} value={values[field.key]} />
            ))}
          </dl>
        </div>
      ))}
    </div>
  );
}
