/* Claim — decision. The one screen where the desk commits.
   Commit model: STAGED. The outcome, the part amount, the reason and the
   justification are all form fields; nothing is recorded until the submit, the
   submit is disabled until the form is dirty and valid, Cancel appears once
   dirty, and the submit shows pending. The header's transitions navigate or
   open their own dialog.
   Data state: populated. The four branches below are record states, not data
   states: already decided · not yet assessed · evidence outstanding · ready. */
(() => {
  const {
    Button, Input, Textarea, Select, Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Alert, AlertTitle, AlertDescription, AlertAction, Radio, Badge, Separator,
  } = window.OriginDesignSystem_7c998b;

  const MIN_JUSTIFICATION = 40;

  function DecisionOption({ outcome, selected, hint, disabled, onSelect, children }) {
    return (
      <div
        className="cd-option"
        role="radio"
        aria-checked={selected}
        aria-disabled={disabled || undefined}
        tabIndex={disabled ? -1 : 0}
        onClick={() => { if (!disabled) onSelect(); }}
        onKeyDown={(e) => { if (!disabled && (e.key === " " || e.key === "Enter")) { e.preventDefault(); onSelect(); } }}
      >
        <Radio checked={selected} disabled={disabled} onSelect={() => { if (!disabled) onSelect(); }} name="cd-outcome" />
        <span className="cd-option__body">
          <span className="cd-option__label">{outcome.label}</span>
          <span className="cd-option__hint">{hint}</span>
        </span>
        {selected && children ? <div className="cd-option__extra" onClick={(e) => e.stopPropagation()}>{children}</div> : null}
      </div>
    );
  }

  /* The letter the customer eventually reads, rendered from the values in the
     form — not a description of them. */
  function OfferPreview({ claim, outcome, amount, reasonValue, justification }) {
    if (!outcome) return <p className="cd-note">Pick an outcome and the letter builds here, from the figures and the words in the form.</p>;
    return (
      <div className="cd-letter">
        <p>Dear {claim.customer},</p>
        <p>Claim {claim.id}, container {claim.container}, {claim.vessel} {claim.voyage}.</p>
        {outcome === "reject" ? (
          <p>We have completed our investigation and regret that we cannot accept liability for this loss. Our reason is {(labelOf(REJECT_REASONS, reasonValue) || "—").toLowerCase()}.</p>
        ) : (
          <p>We have completed our investigation and offer <strong>{isNaN(amount) ? "—" : formatMoney(amount)}</strong> in full and final settlement of this claim.</p>
        )}
        {justification.trim() ? <p className="cd-letter__quote">{justification.trim()}</p> : null}
        <p>{CLAIMS_USER.name}, {CLAIMS_USER.role}<br />{CLAIMS_CARRIER.name}</p>
      </div>
    );
  }

  function RecordedDecision({ claim, onNavigate }) {
    const outcomeLabel = labelOf(DECISION_OUTCOMES, claim.decision.outcome);
    return (
      <Card className="cd-decide">
        <CardHeader>
          <CardTitle>{outcomeLabel} — recorded {formatAbsolute(claim.decision.decidedAt)}</CardTitle>
          <CardDescription>
            By {claim.decision.decidedBy}
            {claim.decision.signedOffBy ? ", signed off by " + claim.decision.signedOffBy + " above the " + formatMoney(CLAIM_POLICY.authorityLimitCents) + " authority limit." : ", within the " + formatMoney(CLAIM_POLICY.authorityLimitCents) + " authority limit."}
          </CardDescription>
        </CardHeader>
        <CardPanel>
          <div className="cd-lg">
            {claim.settlement ? (
              <LedgerRow label="Settled at" hint={"Payment " + (claim.settlement.reference || "not yet referenced")} value={<span className="cd-figure" style={{ fontSize: "var(--text-2xl)" }}>{formatMoney(claim.settlement.amountCents)}</span>} />
            ) : null}
            {claim.decision.rejectReason ? (
              <LedgerRow label="Reason" hint="From the rejection list" value={labelOf(REJECT_REASONS, claim.decision.rejectReason)} />
            ) : null}
          </div>
          {claim.decision.justification ? (
            <div style={{ marginTop: "var(--space-5)" }} className="cd-letter">
              <span className="cd-h3">Justification sent to the customer</span>
              <p className="cd-letter__quote">{claim.decision.justification}</p>
            </div>
          ) : null}
        </CardPanel>
        <CardFooter className="cd-form-foot">
          <span className="cd-form-foot__note">A recorded decision is not edited here. If the customer disputes it, the offer comes back through Responses.</span>
          {claim.settlement ? <Button variant="outline" onClick={() => onNavigate("/payments")}>Open on the payments desk</Button> : null}
          {claim.response ? <Button variant="ghost" onClick={() => onNavigate("/responses")}>See the customer's response<Icon name="arrow-right" /></Button> : null}
        </CardFooter>
      </Card>
    );
  }

  function DecisionScreen({ claim, now, onNavigate, onTransition, onRecordDecision }) {
    const [outcome, setOutcome] = React.useState("");
    const [partAmount, setPartAmount] = React.useState("");
    const [reasonValue, setReasonValue] = React.useState("");
    const [justification, setJustification] = React.useState("");
    const [submitted, setSubmitted] = React.useState(false);
    const [saving, setSaving] = React.useState(false);
    React.useEffect(() => { setOutcome(""); setPartAmount(""); setReasonValue(""); setJustification(""); setSubmitted(false); }, [claim.id]);

    const ledger = assess(claim);
    const missing = CLAIM_FLAGS.missingMandatory(claim);
    const payable = ledger.payable;
    const amount = outcome === "approve_full" ? payable : outcome === "approve_part" ? parseMoney(partAmount) : 0;
    const needsSignoff = outcome && outcome !== "reject" && CLAIM_FLAGS.needsSignoff(isNaN(amount) ? 0 : amount);
    const justificationShort = justification.trim().length < MIN_JUSTIFICATION;
    const errors = {};
    if (outcome === "approve_part") {
      if (isNaN(amount) || amount <= 0) errors.amount = "Enter the amount you are offering.";
      else if (amount > payable) errors.amount = "A part approval cannot exceed the payable figure of " + formatMoney(payable) + ".";
      if (justificationShort) errors.justification = "A part approval needs a written justification of at least " + MIN_JUSTIFICATION + " characters.";
    }
    if (outcome === "reject") {
      if (!reasonValue) errors.reason = "Pick the reason the claim is refused.";
      if (justificationShort) errors.justification = "A rejection needs a written justification of at least " + MIN_JUSTIFICATION + " characters.";
    }
    const dirty = !!outcome;
    const valid = dirty && Object.keys(errors).length === 0;
    const submitLabel = outcome === "reject" ? "Reject claim" : needsSignoff ? "Send for sign-off" : "Approve claim";

    const submit = () => {
      setSubmitted(true);
      if (!valid) return;
      setSaving(true);
      window.setTimeout(() => {
        setSaving(false);
        onRecordDecision(claim, {
          outcome: outcome,
          amountCents: outcome === "reject" ? 0 : amount,
          rejectReason: outcome === "reject" ? reasonValue : null,
          justification: justification.trim() || null,
          needsSignoff: needsSignoff,
        });
      }, 600);
    };

    const body = () => {
      if (claim.decision) return <RecordedDecision claim={claim} onNavigate={onNavigate} />;
      if (missing.length) {
        return (
          <Card className="cd-decide">
            <CardHeader>
              <CardTitle>The decision surface is closed</CardTitle>
              <CardDescription>A decision on incomplete evidence is a decision we cannot defend, so this claim cannot be decided yet.</CardDescription>
            </CardHeader>
            <CardPanel>
              <Alert variant="warning">
                <AlertTitle>{missing.length === 1 ? "One mandatory document is outstanding" : missing.length + " mandatory documents are outstanding"}</AlertTitle>
                <AlertDescription>{missing.map((m) => labelOf(DOCUMENT_TYPES, m)).join(", ")}. Once every mandatory document is on file, the three outcomes open here.</AlertDescription>
                <AlertAction>
                  <Button variant="outline" size="sm" onClick={() => onNavigate("/claims/" + claim.id + "/evidence")}>Open evidence</Button>
                </AlertAction>
              </Alert>
            </CardPanel>
          </Card>
        );
      }
      if (ledger.assessed === null) {
        return (
          <Card className="cd-decide">
            <CardHeader>
              <CardTitle>Assess the claim first</CardTitle>
              <CardDescription>There is nothing to approve until the adjustments and the cap have been worked out.</CardDescription>
            </CardHeader>
            <CardPanel>
              <Alert variant="info">
                <AlertTitle>No assessment on file</AlertTitle>
                <AlertDescription>{claim.customer} claims {formatMoney(claim.claimedCents)}. Record depreciation, salvage and the deductible on the assessment, and the payable figure appears here.</AlertDescription>
                <AlertAction>
                  <Button variant="outline" size="sm" onClick={() => onNavigate("/claims/" + claim.id)}>Open assessment</Button>
                </AlertAction>
              </Alert>
            </CardPanel>
          </Card>
        );
      }
      return (
        <Card className="cd-decide">
          <CardHeader>
            <CardTitle>Decide {claim.id}</CardTitle>
            <CardDescription>
              Payable today is {formatMoney(payable)}{ledger.capBinds ? ", held at the bill of lading cap — " + formatMoney(ledger.cappedAway) + " of assessed liability is not payable" : ", comfortably inside the cap of " + formatMoney(ledger.cap.cents)}.
            </CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="cd-options" role="radiogroup" aria-label="Decision outcome">
              <DecisionOption
                outcome={DECISION_OUTCOMES[0]}
                selected={outcome === "approve_full"}
                hint={"Offer the full payable figure of " + formatMoney(payable) + " against the " + formatMoney(claim.claimedCents) + " claimed."}
                onSelect={() => setOutcome("approve_full")}
              />
              <DecisionOption
                outcome={DECISION_OUTCOMES[1]}
                selected={outcome === "approve_part"}
                hint="Offer less than the payable figure. The customer reads your justification, so write it for them."
                onSelect={() => setOutcome("approve_part")}
              >
                <div>
                  <label className="cd-option__label" htmlFor="cd-part">Amount offered</label>
                  <div style={{ marginTop: "var(--space-2)", maxWidth: "12rem" }}>
                    <Input id="cd-part" inputMode="decimal" startAddon="$" placeholder={moneyInputValue(payable)} value={partAmount} invalid={submitted && !!errors.amount} onChange={(e) => setPartAmount(e.target.value)} />
                  </div>
                  <p className="cd-note" style={{ marginTop: "var(--space-2)" }}>
                    {submitted && errors.amount ? <span style={{ color: "var(--destructive-foreground)" }}>{errors.amount}</span> : "Anything up to " + formatMoney(payable) + "."}
                  </p>
                </div>
              </DecisionOption>
              <DecisionOption
                outcome={DECISION_OUTCOMES[2]}
                selected={outcome === "reject"}
                hint="Decline liability. A reason from the list and a written justification are both required."
                onSelect={() => setOutcome("reject")}
              >
                <div>
                  <label className="cd-option__label" htmlFor="cd-reason">Reason</label>
                  <div style={{ marginTop: "var(--space-2)", maxWidth: "22rem" }}>
                    <Select id="cd-reason" items={REJECT_REASONS} value={reasonValue} placeholder="Pick a reason" onValueChange={setReasonValue} />
                  </div>
                  {submitted && errors.reason ? <p className="cd-note" style={{ marginTop: "var(--space-2)", color: "var(--destructive-foreground)" }}>{errors.reason}</p> : null}
                </div>
              </DecisionOption>
            </div>

            {outcome === "approve_part" || outcome === "reject" ? (
              <div style={{ marginTop: "var(--space-6)" }}>
                <label className="cd-option__label" htmlFor="cd-just">Justification the customer will read</label>
                <div style={{ marginTop: "var(--space-2)" }}>
                  <Textarea id="cd-just" rows={5} value={justification} invalid={submitted && !!errors.justification}
                    placeholder={outcome === "reject" ? "Explain, in plain words, why the carrier is not liable for this loss." : "Explain which part of the loss we accept, and why the rest is not payable."}
                    onChange={(e) => setJustification(e.target.value)} />
                </div>
                <div className="cd-counter">
                  <span>{submitted && errors.justification ? <span style={{ color: "var(--destructive-foreground)" }}>{errors.justification}</span> : "It goes out under your name, unedited."}</span>
                  <span>{justification.trim().length} of {MIN_JUSTIFICATION} characters</span>
                </div>
              </div>
            ) : null}
          </CardPanel>
          <CardFooter className="cd-form-foot">
            <span className="cd-form-foot__note">
              {!outcome ? "Nothing is recorded until you submit." : needsSignoff
                ? formatMoney(isNaN(amount) ? 0 : amount) + " is above your " + formatMoney(CLAIM_POLICY.authorityLimitCents) + " authority, so " + CLAIMS_MANAGER.name + " (" + CLAIMS_MANAGER.role.toLowerCase() + ") signs off before the offer goes out."
                : outcome === "reject" ? "A rejection is yours to make at any value." : formatMoney(isNaN(amount) ? 0 : amount) + " is inside your " + formatMoney(CLAIM_POLICY.authorityLimitCents) + " authority, so this is yours to approve."}
            </span>
            {dirty ? <Button variant="outline" onClick={() => { setOutcome(""); setPartAmount(""); setReasonValue(""); setJustification(""); setSubmitted(false); }}>Cancel</Button> : null}
            <Button disabled={!dirty} loading={saving} onClick={submit}>{submitLabel}</Button>
          </CardFooter>
        </Card>
      );
    };

    return (
      <div className="cd-page">
        <ClaimHeader claim={claim} now={now} view="decision" onNavigate={onNavigate} onTransition={onTransition} />
        <div className="cd-split">
          <div className="cd-col">{body()}</div>
          <div className="cd-col cd-col--tight">
            <Card>
              <CardHeader>
                <CardTitle>What the customer will see</CardTitle>
                <CardDescription>Built from the figures and the words in the form, not a description of them.</CardDescription>
              </CardHeader>
              <CardPanel>
                {claim.decision ? (
                  <OfferPreview claim={claim} outcome={claim.decision.outcome} amount={claim.settlement ? claim.settlement.amountCents : 0} reasonValue={claim.decision.rejectReason} justification={claim.decision.justification || ""} />
                ) : (
                  <OfferPreview claim={claim} outcome={outcome} amount={amount} reasonValue={reasonValue} justification={justification} />
                )}
              </CardPanel>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Your authority</CardTitle>
                <CardDescription>{CLAIMS_USER.name} · {CLAIMS_USER.role}</CardDescription>
              </CardHeader>
              <CardPanel>
                <dl className="cd-defs">
                  <dt>Decide alone up to</dt><dd className="cd-amount">{formatMoney(CLAIM_POLICY.authorityLimitCents)}</dd>
                  <dt>Payable on this claim</dt><dd className="cd-amount">{payable === null ? "Not assessed" : formatMoney(payable)}</dd>
                  <dt>This decision</dt>
                  <dd className="cd-amount">
                    {claim.decision ? formatMoney(claim.settlement ? claim.settlement.amountCents : 0) : outcome ? formatMoney(isNaN(amount) ? 0 : amount) : "Not chosen yet"}
                  </dd>
                  <dt>Sign-off</dt>
                  <dd>
                    {claim.decision
                      ? (claim.decision.signedOffBy || "Not required")
                      : outcome
                        ? (needsSignoff ? CLAIMS_MANAGER.name : "Not required")
                        : (payable !== null && CLAIM_FLAGS.needsSignoff(payable) ? CLAIMS_MANAGER.name + ", if you approve in full" : "Not required")}
                  </dd>
                </dl>
              </CardPanel>
            </Card>
          </div>
        </div>
      </div>
    );
  }

  Object.assign(window, { DecisionScreen, DecisionOption, OfferPreview });
})();
