import { useState } from "preact/hooks";
import { ListItem } from "@/components/ListItem";
import { Avatar } from "@/components/Avatar";
import { Badge } from "@/components/Badge";
import { SearchInput } from "@/components/SearchInput";
import { CalendarView } from "./CalendarView";
import { ChecklistView } from "./ChecklistView";
import { TilesView } from "./TilesView";
import { EmptyState } from "@/components/EmptyState";
import { resolveBadgeColor } from "@/theme/accents";
import { formatFieldValue, formatNum, getImageField, resolveFK } from "@/utils/format";
import { cleanLabel } from "@/components/FieldLabel";
import type { PageSpec, RecordSpec, DataRow, LayoutMode } from "@/types/spec";
import type { TableData } from "@/hooks/useData";

interface ListViewProps {
  page: PageSpec;
  rec: RecordSpec | undefined;
  data: DataRow[];
  allRecords: RecordSpec[];
  allData: TableData;
  onViewDetail: (table: string, id: string) => void;
  onAdd: () => void;
  onCycleField: (table: string, id: string, field: string, current: string, choices: string[]) => void;
  onDelete: (table: string, id: string) => void;
}

export function ListView({ page, rec, data, allRecords, allData, onViewDetail, onAdd, onCycleField, onDelete }: ListViewProps) {
  const [search, setSearch] = useState("");
  const [layout, setLayout] = useState<string>((page.config?.layout as string) || "list");

  const config = page.config || {};
  const fields = rec ? Object.keys(rec.fields) : [];
  const titleF = config.title || fields.find((f) => f !== "id" && !f.endsWith("_id")) || "id";
  const subtitleF = config.subtitle || fields.find((f) => f !== "id" && f !== titleF && !f.endsWith("_id"));
  const badgeF = config.badge as string | undefined;
  const choices = badgeF && rec ? rec.fields[badgeF]?.choices : null;
  const colorMap = badgeF && rec ? rec.fields[badgeF]?.colors : null;

  const q = search.toLowerCase();
  const filtered = q ? data.filter((row) => Object.values(row).some((v) => String(v).toLowerCase().includes(q))) : data;

  // Resolve subtitle: formatted value or FK
  function getSubtitle(row: DataRow): string {
    if (subtitleF && row[subtitleF] != null && row[subtitleF] !== "") {
      const fmt = formatFieldValue(subtitleF, row[subtitleF], rec?.fields[subtitleF]);
      return fmt ?? formatNum(row[subtitleF]);
    }
    if (rec) {
      for (const [fn, fm] of Object.entries(rec.fields)) {
        if (fm.link && row[fn + "_id"]) {
          const fk = resolveFK(fn + "_id", row[fn + "_id"], rec, allRecords, allData);
          if (fk) return fk.name;
        }
      }
    }
    return "";
  }

  // Detect if there's a date field or boolean field for calendar/checklist
  const dateField = rec ? Object.keys(rec.fields).find((f) => rec.fields[f].type === "date") : undefined;
  const boolField = rec ? Object.keys(rec.fields).find((f) => rec.fields[f].type === "boolean") : undefined;

  const layoutButtons: { key: string; icon: string }[] = [
    { key: "list", icon: "☰" },
    { key: "cards", icon: "▦" },
    ...(badgeF && choices ? [{ key: "kanban", icon: "▥" }] : []),
    { key: "grid", icon: "▤" },
    { key: "tiles", icon: "▩" },
    ...(dateField ? [{ key: "calendar", icon: "📅" }] : []),
    ...(boolField ? [{ key: "checklist", icon: "☑" }] : []),
  ];

  return (
    <div>
      {/* Header */}
      <div class="flex items-center justify-between mb-4">
        <h2 class="text-lg font-semibold">
          {page.name} <span class="text-sm font-normal" style={{ color: "var(--z-muted)" }}>{data.length}</span>
        </h2>
        <div class="flex items-center gap-1.5">
          {data.length > 0 && layoutButtons.map((l) => (
            <button
              key={l.key}
              onClick={() => setLayout(l.key)}
              class="w-7 h-7 rounded-md text-sm transition-all"
              style={{
                background: layout === l.key ? "var(--z-accent-dim)" : "transparent",
                color: layout === l.key ? "var(--z-accent-light)" : "var(--z-muted)",
                border: "none", cursor: "pointer",
              }}
            >{l.icon}</button>
          ))}
          <button
            onClick={onAdd}
            class="px-3 py-1.5 text-xs rounded-[var(--z-radius-button)] font-medium text-white ml-1"
            style={{ background: "var(--z-accent)" }}
          >+ Add</button>
        </div>
      </div>

      {/* Search */}
      <div class="mb-4">
        <SearchInput value={search} onChange={setSearch} placeholder={`Search ${page.name.toLowerCase()}...`} />
      </div>

      {/* Empty state */}
      {data.length === 0 ? (
        <EmptyState title={`No ${page.name.toLowerCase()} yet`} description={`Add your first ${rec?.name?.toLowerCase() || "record"}.`} action={`+ Add ${rec?.name || "Record"}`} onAction={onAdd} />
      ) : q && filtered.length === 0 ? (
        <p class="text-center py-8 text-sm" style={{ color: "var(--z-muted)" }}>No results for "{search}"</p>
      ) : layout === "cards" ? (
        <CardGrid rows={filtered} rec={rec} titleF={titleF} subtitleF={subtitleF} badgeF={badgeF} choices={choices} colorMap={colorMap} getSubtitle={getSubtitle} onViewDetail={onViewDetail} table={page.record!} />
      ) : layout === "kanban" && badgeF && choices ? (
        <KanbanBoard rows={filtered} rec={rec} titleF={titleF} badgeF={badgeF} choices={choices} colorMap={colorMap} getSubtitle={getSubtitle} onViewDetail={onViewDetail} table={page.record!} />
      ) : layout === "grid" ? (
        <GridTable rows={filtered} rec={rec} fields={fields} titleF={titleF} badgeF={badgeF} choices={choices} colorMap={colorMap} onViewDetail={onViewDetail} table={page.record!} />
      ) : layout === "tiles" ? (
        <TilesView rows={filtered} rec={rec} titleField={titleF} onViewDetail={onViewDetail} table={page.record!} />
      ) : layout === "calendar" && dateField ? (
        <CalendarView rows={filtered} rec={rec} dateField={dateField} titleField={titleF} badgeField={badgeF} onViewDetail={onViewDetail} table={page.record!} />
      ) : layout === "checklist" && boolField ? (
        <ChecklistView rows={filtered} rec={rec} titleField={titleF} checkedField={boolField} table={page.record!} onViewDetail={onViewDetail} />
      ) : (
        <RowList rows={filtered} rec={rec} titleF={titleF} badgeF={badgeF} choices={choices} colorMap={colorMap} getSubtitle={getSubtitle} config={config} onViewDetail={onViewDetail} onCycleField={onCycleField} onDelete={onDelete} table={page.record!} allRecords={allRecords} allData={allData} />
      )}
    </div>
  );
}

// ── Row List ──
function RowList({ rows, rec, titleF, badgeF, choices, colorMap, getSubtitle, config, onViewDetail, onCycleField, onDelete, table, allRecords, allData }: any) {
  const groupBy = config.group_by;
  const grouped = groupBy ? groupRows(rows, groupBy) : null;

  function renderItem(row: DataRow) {
    const title = String(row[titleF] || "—");
    const subtitle = getSubtitle(row);
    const image = getImageField(row, rec);
    const badge = badgeF && row[badgeF] ? String(row[badgeF]) : undefined;
    const color = badge ? resolveBadgeColor(badge, choices, colorMap) : undefined;
    return (
      <ListItem
        key={String(row.id)}
        title={title}
        subtitle={subtitle}
        image={image}
        badge={badge}
        badgeColor={color}
        onClick={() => onViewDetail(table, String(row.id))}
        onCycle={badgeF && choices?.length ? () => onCycleField(table, String(row.id), badgeF, String(row[badgeF] || ""), choices) : undefined}
        onDelete={() => onDelete(table, String(row.id))}
      />
    );
  }

  if (grouped) {
    return (
      <div>
        {grouped.map(([groupName, groupRows]) => (
          <div key={groupName}>
            <div class="font-mono text-[var(--z-font-sm)] uppercase tracking-wider mt-4 mb-2" style={{ color: "var(--z-muted)" }}>
              {groupName} <span style={{ opacity: 0.5 }}>({groupRows.length})</span>
            </div>
            <div class="space-y-1">{groupRows.map(renderItem)}</div>
          </div>
        ))}
      </div>
    );
  }

  return <div class="space-y-1">{rows.map(renderItem)}</div>;
}

// ── Card Grid ──
function CardGrid({ rows, rec, titleF, subtitleF, badgeF, choices, colorMap, getSubtitle, onViewDetail, table }: any) {
  return (
    <div class="grid gap-3" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))" }}>
      {rows.map((row: DataRow) => {
        const image = getImageField(row, rec);
        const title = String(row[titleF] || "—");
        const subtitle = getSubtitle(row);
        const badge = badgeF && row[badgeF] ? String(row[badgeF]) : undefined;
        const color = badge ? resolveBadgeColor(badge, choices, colorMap) : undefined;
        return (
          <div
            key={String(row.id)}
            class="rounded-[var(--z-radius-card)] overflow-hidden cursor-pointer transition-all hover:-translate-y-0.5"
            style={{ border: "var(--z-card-border)", boxShadow: "var(--z-card-shadow)", background: "var(--z-card-bg)" }}
            onClick={() => onViewDetail(table, String(row.id))}
          >
            {image ? (
              <img src={image} alt="" class="w-full h-40 object-cover" />
            ) : (
              <div class="h-20 flex items-center justify-center" style={{ background: `var(--z-accent-dim)` }}>
                <span class="text-3xl" style={{ color: "var(--z-accent-light)", opacity: 0.3 }}>{title.charAt(0).toUpperCase()}</span>
              </div>
            )}
            <div class="p-3.5">
              <p class="text-sm font-medium">{title}</p>
              {subtitle && <p class="text-xs mt-1" style={{ color: "var(--z-muted)" }}>{subtitle}</p>}
              {badge && <div class="mt-2"><Badge text={badge} color={color} /></div>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Kanban Board ──
function KanbanBoard({ rows, rec, titleF, badgeF, choices, colorMap, getSubtitle, onViewDetail, table }: any) {
  const columns: Record<string, DataRow[]> = {};
  for (const c of choices) columns[c] = [];
  for (const row of rows) {
    const col = String(row[badgeF] || choices[0]);
    if (columns[col]) columns[col].push(row);
  }

  return (
    <div class="flex gap-3 overflow-x-auto pb-2">
      {Object.entries(columns).map(([colName, colRows]) => {
        const color = resolveBadgeColor(colName, choices, colorMap);
        return (
          <div key={colName} class="min-w-[260px] max-w-[300px] flex-1">
            <div class="font-mono text-[var(--z-font-sm)] uppercase tracking-wider py-2 px-1 flex items-center justify-between" style={{ color: "var(--z-muted)" }}>
              <span class="flex items-center gap-1.5">
                <span class={`w-2 h-2 rounded-full badge-${color}`} />
                {colName}
              </span>
              <span style={{ opacity: 0.5 }}>{colRows.length}</span>
            </div>
            <div class="space-y-1.5">
              {colRows.map((row) => (
                <div
                  key={String(row.id)}
                  class="rounded-[var(--z-radius-card)] cursor-pointer transition-all"
                  style={{ border: "var(--z-card-border)", boxShadow: "var(--z-card-shadow)", background: "var(--z-card-bg)", padding: "var(--z-density-padding)" }}
                  onClick={() => onViewDetail(table, String(row.id))}
                  onMouseOver={(e) => { (e.currentTarget as HTMLElement).style.borderColor = "var(--z-border-hover)"; }}
                  onMouseOut={(e) => { (e.currentTarget as HTMLElement).style.borderColor = "var(--z-border)"; }}
                >
                  <p class="text-[var(--z-font-md)] font-medium">{String(row[titleF] || "—")}</p>
                  {getSubtitle(row) && <p class="text-[var(--z-font-sm)] mt-1" style={{ color: "var(--z-muted)" }}>{getSubtitle(row)}</p>}
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Grid Table ──
function GridTable({ rows, rec, fields, titleF, badgeF, choices, colorMap, onViewDetail, table }: any) {
  const visibleFields = fields.filter((f: string) => f !== "id" && !f.endsWith("_id") && rec?.fields[f]?.type !== "link");
  return (
    <div class="overflow-x-auto">
      <table class="w-full border-collapse text-[var(--z-font-md)]">
        <thead>
          <tr>
            {visibleFields.map((f: string) => (
              <th key={f} class="text-left px-3 py-2 font-mono text-[var(--z-font-sm)] uppercase tracking-wider font-medium whitespace-nowrap" style={{ color: "var(--z-muted)", borderBottom: "1px solid var(--z-border)" }}>
                {cleanLabel(f)}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row: DataRow) => (
            <tr key={String(row.id)} class="cursor-pointer transition-colors" style={{ borderBottom: "1px solid var(--z-border)" }}
              onClick={() => onViewDetail(table, String(row.id))}
              onMouseOver={(e) => { (e.currentTarget as HTMLElement).style.background = "var(--z-card-bg)"; }}
              onMouseOut={(e) => { (e.currentTarget as HTMLElement).style.background = "transparent"; }}
            >
              {visibleFields.map((f: string) => {
                const fm = rec?.fields[f];
                if (fm?.type === "choice" && fm.choices && row[f]) {
                  const c = resolveBadgeColor(String(row[f]), fm.choices, fm.colors);
                  return <td key={f} class="px-3 py-2"><Badge text={String(row[f])} color={c} /></td>;
                }
                const fmt = formatFieldValue(f, row[f], fm);
                return <td key={f} class="px-3 py-2 max-w-[200px] truncate">{fmt ?? (row[f] != null ? String(row[f]) : "—")}</td>;
              })}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function groupRows(rows: DataRow[], field: string): [string, DataRow[]][] {
  const groups: Record<string, DataRow[]> = {};
  const order: string[] = [];
  for (const row of rows) {
    const key = String(row[field] || "Other");
    if (!groups[key]) { groups[key] = []; order.push(key); }
    groups[key].push(row);
  }
  return order.map((k) => [k, groups[k]]);
}
