"use client";

import { useEffect, useId, useMemo, useState } from "react";
import type { StageSectionConfig, SelectOption } from "@/types/form";
import type {
  UseFormRegister,
  FieldValues,
  FieldErrors,
  Control,
} from "react-hook-form";
import { FieldRenderer } from "./fields/FieldRenderer";
import { MatrixGroup } from "./MatrixGroup";
import { StageIcon } from "./StageIcon";
import { evaluate } from "@/lib/conditional";

interface StageSectionProps {
  section: StageSectionConfig;
  register: UseFormRegister<FieldValues>;
  control: Control<FieldValues>;
  errors: FieldErrors;
  /** Live form values, used to evaluate per-field visibility rules. */
  formValues: Record<string, unknown>;
  /** Whether this is the section that matches the current org stage. */
  isCurrent: boolean;
  /**
   * Whether this stage is ahead of the org's current stage. Locked sections
   * still render so the user can see what's coming, but the fields inside
   * are wrapped in a disabled fieldset and never written on submit.
   */
  locked: boolean;
  /** Whether the section starts open. */
  defaultOpen: boolean;
  /** Option groups fetched from CiviCRM, keyed by option_group_id. */
  options: Record<number, SelectOption[]>;
}

/**
 * One accordion card per stage section. Header carries:
 *   - A hand-drawn stage icon (left)
 *   - The stage label (display serif)
 *   - A "Current stage" pill in terracotta if applicable
 *   - A field-count summary on the right
 *   - A chevron that rotates on open
 *
 * The card border thickens and tints leaf-green when current; otherwise it
 * sits quietly on the cream paper.
 */
export function StageSection({
  section,
  register,
  control,
  errors,
  formValues,
  isCurrent,
  locked,
  defaultOpen,
  options,
}: StageSectionProps) {
  const [open, setOpen] = useState(defaultOpen);
  const headingId = useId();
  const panelId = useId();

  // Listen for programmatic expand requests (fired by EngagementForm when a
  // submit fails on a required field inside a collapsed section).
  useEffect(() => {
    const handler = (e: Event) => {
      const detail = (e as CustomEvent<{ sectionId: string }>).detail;
      if (detail?.sectionId === section.id) setOpen(true);
    };
    document.addEventListener("coop-checkin:expand-section", handler);
    return () => document.removeEventListener("coop-checkin:expand-section", handler);
  }, [section.id]);

  const matrixFieldNames = useMemo(() => {
    const names = new Set<string>();
    for (const m of section.matrixGroups ?? []) {
      for (const row of m.rows) for (const f of row.fields) names.add(f);
    }
    return names;
  }, [section.matrixGroups]);

  const visibleFields = section.fields.filter(
    (f) => evaluate(f.visibleWhen, formValues) && !matrixFieldNames.has(f.name),
  );

  const fieldCount =
    visibleFields.length +
    (section.matrixGroups ?? []).reduce(
      (n, g) => n + g.rows.reduce((m, r) => m + r.fields.length, 0),
      0,
    );

  const cardClass = isCurrent
    ? "border-2 border-leaf-600 shadow-[0_1px_0_0_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(60,80,40,0.18)] bg-white/95"
    : locked
      ? "border border-dashed border-rule bg-paper-2/30 shadow-none"
      : "border border-rule bg-white/95 shadow-sm";

  const buttonClass = isCurrent
    ? "bg-leaf-50/60"
    : locked
      ? "hover:bg-paper-2/50"
      : "hover:bg-paper-2/60";

  return (
    <section
      aria-labelledby={headingId}
      className={"overflow-hidden rounded-lg transition " + cardClass}
    >
      <h2 id={headingId} className="m-0">
        <button
          type="button"
          onClick={() => setOpen((v) => !v)}
          aria-expanded={open}
          aria-controls={panelId}
          className={
            "group relative flex w-full items-center gap-4 px-5 py-4 text-left transition-colors sm:px-6 " +
            buttonClass
          }
        >
          <StageRankMark rank={section.rank} isCurrent={isCurrent} locked={locked} />
          <span className="flex-1 min-w-0">
            <span
              className={
                "block font-display text-lg font-medium leading-tight tracking-tight sm:text-xl " +
                (locked ? "text-ink-soft" : "text-ink")
              }
            >
              {section.label}
            </span>
            <span className="mt-1 flex items-center gap-3 text-xs text-ink-mute">
              {isCurrent && (
                <span className="inline-flex items-center gap-1.5 rounded-full border border-clay-200 bg-clay-100/70 px-2 py-0.5 font-medium text-clay-700 uppercase tracking-[0.08em]">
                  <span className="h-1.5 w-1.5 rounded-full bg-clay-600" aria-hidden />
                  Current stage
                </span>
              )}
              {locked && (
                <span className="inline-flex items-center gap-1.5 rounded-full border border-rule bg-paper px-2 py-0.5 font-medium text-ink-mute uppercase tracking-[0.08em]">
                  <LockGlyph />
                  Upcoming
                </span>
              )}
              <span className="tabular-nums">
                {fieldCount} {fieldCount === 1 ? "field" : "fields"}
              </span>
            </span>
          </span>
          <Chevron open={open} />
        </button>
      </h2>

      <div
        id={panelId}
        role="region"
        aria-labelledby={headingId}
        hidden={!open}
        className={"border-t " + (locked ? "border-rule" : "border-rule-soft")}
      >
        <fieldset
          disabled={locked}
          aria-disabled={locked || undefined}
          className={
            "px-5 py-6 sm:px-7 sm:py-7 " +
            (locked ? "opacity-80" : "")
          }
        >
          {locked && <LockedBanner />}
          {section.intro && (
            <p className="mb-6 max-w-prose text-[15px] leading-relaxed text-ink-soft">
              {section.intro}
            </p>
          )}
          {(section.matrixGroups ?? []).length > 0 && (
            <div className="mb-7 space-y-5">
              {section.matrixGroups!.map((g) => (
                <MatrixGroup key={g.id} group={g} register={register} />
              ))}
            </div>
          )}
          {visibleFields.length === 0 && (section.matrixGroups ?? []).length === 0 ? (
            <p className="text-sm italic text-ink-mute">No fields are visible at this stage.</p>
          ) : visibleFields.length === 0 ? null : (
            <div className="grid grid-cols-1 gap-x-7 gap-y-5 md:grid-cols-2">
              {visibleFields.map((f) => {
                const resolvedOptions = f.optionGroupId ? options[f.optionGroupId] : undefined;
                const wide =
                  f.type === "textarea" ||
                  f.type === "boolean" ||
                  f.type === "multiselect";
                return (
                  <div key={f.name} className={wide ? "md:col-span-2" : ""}>
                    <FieldRenderer
                      field={f}
                      register={register}
                      control={control}
                      errors={errors}
                      readonlyValue={formValues[f.name]}
                      resolvedOptions={resolvedOptions}
                    />
                  </div>
                );
              })}
            </div>
          )}
        </fieldset>
      </div>
    </section>
  );
}

/**
 * Stage rank mark: the number sits in a small circle, with the hand-drawn
 * icon offset behind it. When current, the ring is leaf-green and the
 * number is white-on-green; otherwise it's quiet.
 */
function StageRankMark({
  rank,
  isCurrent,
  locked,
}: {
  rank: number;
  isCurrent: boolean;
  locked: boolean;
}) {
  const iconClass = isCurrent
    ? "text-leaf-700 opacity-100"
    : locked
      ? "text-ink-mute opacity-30"
      : "text-leaf-600 opacity-50";
  const badgeClass = isCurrent
    ? "bg-leaf-700 text-paper"
    : locked
      ? "bg-paper text-ink-mute border border-dashed border-rule"
      : "bg-paper text-ink-soft border border-rule";
  return (
    <span aria-hidden className="relative inline-flex h-12 w-12 flex-shrink-0 items-center justify-center">
      <StageIcon
        rank={rank}
        className={"absolute inset-0 h-12 w-12 transition-opacity " + iconClass}
      />
      <span
        className={
          "relative z-10 inline-flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold tabular-nums shadow-sm " +
          badgeClass
        }
        style={{ marginLeft: 28, marginTop: 28 }}
      >
        {rank}
      </span>
    </span>
  );
}

function LockGlyph() {
  return (
    <svg
      aria-hidden
      viewBox="0 0 12 12"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.25"
      strokeLinecap="round"
      strokeLinejoin="round"
      className="h-3 w-3"
    >
      <rect x="2.5" y="5.5" width="7" height="5" rx="0.75" />
      <path d="M4 5.5V4a2 2 0 0 1 4 0v1.5" />
    </svg>
  );
}

function LockedBanner() {
  return (
    <div
      role="note"
      className="mb-5 flex items-start gap-3 rounded-md border border-dashed border-rule bg-paper px-4 py-3"
    >
      <span aria-hidden className="mt-0.5 text-ink-mute">
        <LockGlyph />
      </span>
      <p className="text-xs leading-relaxed text-ink-soft">
        <span className="font-medium text-ink-soft">A look ahead.</span>{" "}
        These fields will become editable when your co-op reaches this stage. They&apos;re visible
        now so you can preview the framework you&apos;ll be working through.
      </p>
    </div>
  );
}

function Chevron({ open }: { open: boolean }) {
  return (
    <svg
      aria-hidden
      viewBox="0 0 20 20"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.5"
      strokeLinecap="round"
      className={"h-5 w-5 flex-shrink-0 text-ink-mute transition-transform duration-300 " + (open ? "rotate-180" : "")}
    >
      <path d="M5 8 L10 13 L15 8" />
    </svg>
  );
}

