import type { ReactElement } from "react";

import { cn } from "@/lib/utils";

interface ProductDetailCategory {
  name?: string | null;
}

type MeasurementValue = string | number | null | undefined;

export interface ProductDetailGridProps {
  id?: string | null;
  brand?: string | null;
  size?: string | null;
  condition?: string | null;
  conditionLabel?: string | null;
  colors?: string[] | null;
  category?: ProductDetailCategory | null;
  measurements?: Record<string, MeasurementValue> | null;
  created_at?: string | null;
  className?: string;
}

interface DetailRow {
  label: string;
  value: DetailValue;
  testId?: string;
}

type DetailValue = string | number | ReactElement;

interface MeasurementRow {
  key: string;
  label: string;
  value: string;
}

function cleanText(value?: string | null): string | null {
  const trimmed = value?.trim();
  return trimmed ? trimmed : null;
}

function formatListedDate(value?: string | null): string | null {
  const raw = cleanText(value);
  if (!raw) return null;

  const date = new Date(raw);
  if (Number.isNaN(date.getTime())) return null;

  return new Intl.DateTimeFormat("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
    timeZone: "UTC",
  }).format(date);
}

function formatMeasurementLabel(key: string): string {
  const normalized = key.replace(/[_-]+/g, " ").trim();
  if (!normalized) return "Measurement";

  return normalized
    .split(/\s+/)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(" ");
}

function normalizeMeasurements(
  measurements?: Record<string, MeasurementValue> | null,
): MeasurementRow[] {
  return Object.entries(measurements ?? {})
    .map(([key, value]) => {
      const normalizedValue = value == null ? null : cleanText(String(value));
      if (!normalizedValue) return null;

      return {
        key,
        label: formatMeasurementLabel(key),
        value: normalizedValue,
      };
    })
    .filter((row): row is MeasurementRow => row !== null)
    .sort((a, b) => a.label.localeCompare(b.label));
}

function normalizeColors(colors?: string[] | null): string[] {
  return (colors ?? [])
    .map((color) => cleanText(color))
    .filter((color): color is string => color !== null);
}

function shortenItemId(id: string): string {
  if (id.length <= 14) return id;

  return `${id.slice(0, 8)}...${id.slice(-4)}`;
}

function formatCondition(
  condition?: string | null,
  conditionLabel?: string | null,
): DetailValue | null {
  const code = cleanText(condition);
  const label = cleanText(conditionLabel);

  if (!code && !label) return null;
  if (!code || code === label) return label ?? code;

  return (
    <span>
      {label ?? code}
      {label ? <span className="ml-1 text-xs text-slate-500">({code})</span> : null}
    </span>
  );
}

function DetailField({ row }: { row: DetailRow }) {
  return (
    <div data-testid={row.testId}>
      <dt className="text-xs font-semibold uppercase tracking-wide text-slate-500">
        {row.label}
      </dt>
      <dd className="mt-1 break-words text-sm font-medium text-slate-900">{row.value}</dd>
    </div>
  );
}

export function ProductDetailGrid({
  id,
  brand,
  size,
  condition,
  conditionLabel,
  colors,
  category,
  measurements,
  created_at,
  className,
}: ProductDetailGridProps) {
  const colorValues = normalizeColors(colors);
  const listedDate = formatListedDate(created_at);
  const itemId = cleanText(id);
  const conditionValue = formatCondition(condition, conditionLabel);
  const measurementRows = normalizeMeasurements(measurements);
  const brandValue = cleanText(brand);
  const sizeValue = cleanText(size);
  const categoryValue = cleanText(category?.name);
  const colorValue = colorValues.length > 0 ? colorValues.join(", ") : null;

  const possibleDetailRows: Array<DetailRow | null> = [
    brandValue ? { label: "Brand", value: brandValue } : null,
    sizeValue ? { label: "Size", value: sizeValue } : null,
    conditionValue ? { label: "Condition", value: conditionValue } : null,
    colorValue ? { label: "Color", value: colorValue } : null,
    categoryValue ? { label: "Category", value: categoryValue } : null,
    listedDate ? { label: "Listed", value: listedDate } : null,
    itemId
      ? {
          label: "Item ID",
          value: (
            <code
              className="select-all rounded bg-slate-100 px-1.5 py-0.5 font-mono text-xs text-slate-700"
              title={itemId}
            >
              {shortenItemId(itemId)}
            </code>
          ),
          testId: "item-id",
        }
      : null,
  ];
  const detailRows = possibleDetailRows.filter((row): row is DetailRow => row !== null);

  if (detailRows.length === 0 && measurementRows.length === 0) return null;

  return (
    <section
      aria-labelledby="item-details-heading"
      className={cn("rounded-lg border border-slate-200 bg-white p-5", className)}
    >
      <h2
        id="item-details-heading"
        className="text-sm font-semibold uppercase tracking-wide text-slate-500"
      >
        Item details
      </h2>

      {detailRows.length > 0 ? (
        <dl className="mt-4 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2">
          {detailRows.map((row) => (
            <DetailField key={row.label} row={row} />
          ))}
        </dl>
      ) : null}

      {measurementRows.length > 0 ? (
        <div className="mt-5 border-t border-slate-100 pt-5">
          <h3 className="text-xs font-semibold uppercase tracking-wide text-slate-500">
            Measurements
          </h3>
          <dl className="mt-3 grid grid-cols-1 gap-x-6 gap-y-3 sm:grid-cols-2">
            {measurementRows.map((row) => (
              <div key={`${row.key}-${row.value}`}>
                <dt className="text-xs text-slate-500">{row.label}</dt>
                <dd className="mt-0.5 break-words text-sm font-medium text-slate-900">
                  {row.value}
                </dd>
              </div>
            ))}
          </dl>
        </div>
      ) : null}
    </section>
  );
}
