// In-dock card showing a Socrates-proposed change.
//
// Displays: reasoning, op summary, impact summary (added/removed/changed +
// validation diff), and Accept / Reject controls. Accept calls into the
// ModelStore which routes through the same applyOps + persistence pipeline
// as user-originated edits.

"use client";

import { useState } from "react";
import type { ImpactSummary } from "../../lib/sysml/impact";
import type { ModelOp } from "../../lib/sync/ops";

export interface ProposalPayload {
  reasoning: string;
  ops: ModelOp[];
  impactSummary: ImpactSummary;
  meta?: { provider?: string; model?: string };
}

interface ProposalCardProps {
  proposal: ProposalPayload;
  onAccept: () => Promise<void> | void;
  onReject: () => void;
  pending?: boolean;
}

export function ProposalCard({ proposal, onAccept, onReject, pending }: ProposalCardProps) {
  const [busy, setBusy] = useState(false);
  const { reasoning, ops, impactSummary } = proposal;

  async function accept() {
    if (busy) return;
    setBusy(true);
    try {
      await onAccept();
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className={`proposal-card ${pending ? "proposal-card-pending" : ""}`}>
      <div className="proposal-card-head">
        <span className="proposal-card-tag">PROPOSAL</span>
        <span className="proposal-card-stats">
          {summarizeStats(impactSummary)}
        </span>
      </div>

      <div className="proposal-card-reasoning">{reasoning}</div>

      {ops.length > 0 && (
        <details className="proposal-card-ops" open>
          <summary>Ops · {ops.length}</summary>
          <ul>
            {ops.map((op, i) => (
              <li key={i}>{summarizeOp(op)}</li>
            ))}
          </ul>
        </details>
      )}

      {(impactSummary.added.length > 0 || impactSummary.removed.length > 0 || impactSummary.changed.length > 0) && (
        <div className="proposal-card-section">
          <div className="proposal-card-section-label">Impact</div>
          <div className="proposal-card-impact-grid">
            {impactSummary.added.length > 0 && (
              <div className="proposal-card-impact-row">
                <span className="proposal-card-impact-key">+ added</span>
                <span className="proposal-card-impact-val">
                  {impactSummary.added.map(e => `${e.label} (${e.kind})`).join(", ")}
                </span>
              </div>
            )}
            {impactSummary.removed.length > 0 && (
              <div className="proposal-card-impact-row">
                <span className="proposal-card-impact-key">− removed</span>
                <span className="proposal-card-impact-val">
                  {impactSummary.removed.map(e => `${e.label} (${e.kind})`).join(", ")}
                </span>
              </div>
            )}
            {impactSummary.changed.length > 0 && (
              <div className="proposal-card-impact-row">
                <span className="proposal-card-impact-key">~ changed</span>
                <span className="proposal-card-impact-val">
                  {impactSummary.changed.map(e => `${e.label} (${e.kind})`).join(", ")}
                </span>
              </div>
            )}
          </div>
        </div>
      )}

      {(impactSummary.issuesCreated.length > 0 || impactSummary.issuesResolved.length > 0) && (
        <div className="proposal-card-section">
          <div className="proposal-card-section-label">Validation</div>
          {impactSummary.issuesResolved.length > 0 && (
            <ul className="proposal-card-issue-list proposal-card-issues-resolved">
              {impactSummary.issuesResolved.slice(0, 4).map((i, idx) => (
                <li key={idx}>✓ resolves {i.code}: {i.message}</li>
              ))}
            </ul>
          )}
          {impactSummary.issuesCreated.length > 0 && (
            <ul className="proposal-card-issue-list proposal-card-issues-created">
              {impactSummary.issuesCreated.slice(0, 4).map((i, idx) => (
                <li key={idx}>⚠ creates {i.code}: {i.message}</li>
              ))}
            </ul>
          )}
        </div>
      )}

      {!impactSummary.ok && (
        <div className="proposal-card-section proposal-card-error">
          <div className="proposal-card-section-label">Cannot apply</div>
          <ul className="proposal-card-issue-list">
            {impactSummary.errors.map((e, i) => (
              <li key={i}>{e.code}: {e.message}</li>
            ))}
          </ul>
        </div>
      )}

      <div className="proposal-card-actions">
        <button
          type="button"
          className="proposal-card-btn proposal-card-btn-primary"
          onClick={accept}
          disabled={busy || pending || !impactSummary.ok || ops.length === 0}
        >
          {busy ? "Applying…" : "Accept"}
        </button>
        <button
          type="button"
          className="proposal-card-btn"
          onClick={onReject}
          disabled={busy || pending}
        >
          Reject
        </button>
      </div>

      {proposal.meta?.model && (
        <div className="proposal-card-meta">
          via {proposal.meta.provider} · {proposal.meta.model}
        </div>
      )}
    </div>
  );
}

function summarizeStats(impact: ImpactSummary): string {
  if (!impact.ok) return "would not apply";
  const parts: string[] = [];
  const { stats } = impact;
  if (stats.blocksDelta) parts.push(`${signed(stats.blocksDelta)} block${Math.abs(stats.blocksDelta) === 1 ? "" : "s"}`);
  if (stats.associationsDelta) parts.push(`${signed(stats.associationsDelta)} assoc`);
  if (stats.constraintsDelta) parts.push(`${signed(stats.constraintsDelta)} constraint${Math.abs(stats.constraintsDelta) === 1 ? "" : "s"}`);
  if (stats.requirementsDelta) parts.push(`${signed(stats.requirementsDelta)} req${Math.abs(stats.requirementsDelta) === 1 ? "" : "s"}`);
  if (stats.issuesDelta) parts.push(`${signed(stats.issuesDelta)} issue${Math.abs(stats.issuesDelta) === 1 ? "" : "s"}`);
  if (parts.length === 0) parts.push("structural rearrangement");
  return parts.join(" · ");
}
function signed(n: number): string {
  return n > 0 ? `+${n}` : `${n}`;
}

function summarizeOp(op: ModelOp): string {
  switch (op.kind) {
    case "add-block":
      return `+ block "${op.block.label}" (${op.block.kind})`;
    case "remove-block":
      return `− block ${op.blockId}`;
    case "update-block":
      return `~ block ${op.blockId}`;
    case "add-association":
      return `+ assoc ${op.association.fromBlockId}→${op.association.toBlockId} (${op.association.kind})`;
    case "remove-association":
      return `− assoc ${op.associationId}`;
    case "update-association":
      return `~ assoc ${op.associationId}`;
    case "add-constraint":
      return `+ constraint "${op.constraint.label}"`;
    case "remove-constraint":
      return `− constraint ${op.constraintId}`;
    case "update-constraint":
      return `~ constraint ${op.constraintId}`;
    case "add-requirement":
      return `+ req ${op.requirement.tag}`;
    case "remove-requirement":
      return `− req ${op.requirementId}`;
    case "update-requirement":
      return `~ req ${op.requirementId}`;
    case "add-property":
      return `+ property ${op.blockId}.${op.property.name}`;
    case "update-property":
      return `~ property ${op.blockId}.${op.propertyId}`;
    case "remove-property":
      return `− property ${op.blockId}.${op.propertyId}`;
    case "add-relation":
      return `+ relation ${op.requirementId}.${op.relation.kind}`;
    case "remove-relation":
      return `− relation ${op.requirementId}[${op.relationIndex}]`;
  }
}
