// The Video script block — the words a video screen will SAY, where an author
// can read them.
//
// ── ★ WHY THIS EXISTS ───────────────────────────────────────────────────────
//
// Omar's condition for letting the document-to-course flow propose video
// screens at all, 2026-09-18:
//
//   "When source content is assigned to a video layout, I must be able to read
//    the exact text assigned to it in the editor, even while the layout
//    displays a placeholder video. That text must remain available after saving
//    and reopening the course."
//
// Until this existed, a generated video screen would have shown a stock reel
// and nothing else — the author would have had no way to know which part of
// their document had become a video, which is the rule the video types were
// held back for (`course-outline.ts` records that decision and its release).
//
// ── ★ WHERE THE TEXT LIVES, AND WHY NOT ON THE DRAFT ────────────────────────
//
// In `videoScripts`, a sibling of `layoutDrafts` inside `authoringState`.
// NOT on the layout draft, and that is not a preference:
// `toDraftContent` spreads a draft into the exported `content`, every layout
// schema is `.strict()`, and the gateway's sanitiser drops unrecognised keys
// and still answers 200. A script kept on the draft would survive every check
// in the browser and be gone after the next server load — the author would
// type it, watch "Saved", and lose it. `generation-state.js` carries the full
// account; `fe-draft-slices-round-trip.test.ts` is what proves the round trip.
//
// A second consequence, and it is the one Omar asked for in the same breath:
// because it never reaches `content`, the script cannot reach the exported
// package either. It is production notes, not learner-facing copy.
//
// ── ★ "NEEDS RECORDING" IS DERIVED, NEVER STORED ────────────────────────────
//
// From `isPlaceholderMedia(videoUrl)`. Upload a real video and the chip clears
// itself, with nothing to remember to update — a stored flag would be a second
// statement of the same fact, free to disagree with the first
// (`feedback_a_setting_that_describes_state_is_not_a_preference`).

(function () {
  'use strict';

  /** Words in a script — the number a person reading it actually wants. */
  function wordCount(text) {
    var t = (text || '').trim();
    return t ? t.split(/\s+/).length : 0;
  }

  /**
   * Roughly how long this takes to say, as `m:ss`, or null when there is
   * nothing to say.
   *
   * ⚠️ 150 words a minute is a STATED ASSUMPTION, not a measurement, so the
   * label says "about" and the number is never presented as a duration the
   * product will honour. A figure that looks measured and is not is worse than
   * no figure (`feedback_a_plausible_placeholder_is_worse_than_an_obvious_one`).
   */
  function spokenLength(text) {
    var w = wordCount(text);
    if (!w) return null;
    var secs = Math.round((w / 150) * 60);
    var m = Math.floor(secs / 60);
    var s = secs % 60;
    return m + ':' + (s < 10 ? '0' : '') + s;
  }

  /**
   * Does this slot still hold the stand-in reel?
   *
   * Exported so the panel HEADER can carry the chip. Derived, never stored —
   * upload a real video and it clears itself, with nothing to remember to update
   * (`feedback_a_setting_that_describes_state_is_not_a_preference`).
   */
  function videoNeedsRecording(videoUrl) {
    return typeof window.isPlaceholderMedia === 'function'
      ? window.isPlaceholderMedia(videoUrl)
      : false;
  }

  /**
   * ★ `embedded` — the script INSIDE the Video media panel (Omar, 2026-09-18:
   * "Make the editable Video script field part of the existing Video media
   * panel… establish a clear relationship between the video, its script and its
   * recording status").
   *
   * It used to be a panel of its own, sitting above Video media, which made the
   * two read as unrelated settings that happened to be adjacent. They are one
   * thing: a video, the words it will say, and whether it has been recorded yet.
   * Embedded, the chip moves to the panel header — where it describes the VIDEO,
   * which is what it was always about — and the script sits under the media it
   * belongs to, behind a rule that shows the relationship rather than asserting
   * it.
   *
   * The standalone form is kept for any caller that still wants a panel; nothing
   * about the text, its editing, its storage or the chip's derivation changes
   * between the two.
   *
   * 2026-09-19, the second step of the same instruction ("The Script — What
   * this video will say section must sit inside Video media … video above,
   * editable text below"): the embedded form's one placement is now INSIDE the
   * Video media card itself — `VideoMediaBlock` mounts it beneath the preview
   * and its toolbar, and the toolbar carries a text icon that shows or hides
   * it (visible by default). The card draws this section's separating rule the
   * same way it separates its header and toolbar, so the wrapper below no
   * longer draws one of its own — two rules under the toolbar read as a
   * drawing mistake, not a relationship.
   */
  function VideoScriptBlock(props) {
    var EditorBlock = window.EditorBlock;
    var entry = props.script || null;
    var text = entry && typeof entry.text === 'string' ? entry.text : '';
    var generated = !!(entry && entry.source === 'generated');
    // ★ The chip follows the SLOT, not the script: a screen whose video is
    //   still the stand-in reel needs recording whether or not anyone has
    //   written the words yet.
    var needsRecording = videoNeedsRecording(props.videoUrl);
    var length = spokenLength(text);

    var body = (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <textarea className="field" data-testid="video-script-input"
          aria-label="Video script"
          value={text}
          placeholder={'What the video says. Nobody reads this on screen — it is the text to be recorded.'}
          onChange={function (e) { props.onChange(e.target.value); }}
          style={{ width: '100%', minHeight: 132, lineHeight: 1.55, resize: 'vertical' }} />
        <div style={{ display: 'flex', gap: 10, alignItems: 'baseline', flexWrap: 'wrap',
          fontSize: 11.5, color: 'var(--text-faint)' }}>
          {length && <span>about {length} to say</span>}
          {/* Said only when it IS generated. A script the author wrote gets no
              provenance line rather than a wrong one. */}
          {generated && <span data-testid="script-from-document">
            taken from the uploaded document
          </span>}
          <span style={{ marginLeft: 'auto' }}>Not exported — production notes only</span>
        </div>
      </div>
    );

    if (props.embedded) {
      return (
        <div data-testid="video-script-embedded"
          style={{
            // No border or offset of its own since 2026-09-19: the host card
            // (`VideoMediaBlock`) draws the full-width rule that separates this
            // section from the toolbar above it — the same way it separates its
            // header and preview — and owns the padding. The rule is still the
            // relationship; it just belongs to the card that relates the three
            // things (`feedback_one_design_system_reuse_the_hosts_chrome`).
            display: 'flex', flexDirection: 'column', gap: 8,
          }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
            <span style={{
              fontSize: 11, fontWeight: 600, letterSpacing: '.04em',
              textTransform: 'uppercase', color: 'var(--text-muted)',
            }}>Script</span>
            <span style={{ fontSize: 11.5, color: 'var(--text-faint)' }}>
              what this video will say
            </span>
            {text ? (
              <span style={{ marginLeft: 'auto', fontSize: 11.5, color: 'var(--text-faint)' }}>
                {wordCount(text) + ' words'}
              </span>
            ) : null}
          </div>
          {body}
        </div>
      );
    }

    return (
      <EditorBlock label="Video script"
        count={text ? wordCount(text) + ' words' : null}
        action={needsRecording ? (
          <span data-testid="needs-recording" style={{
            fontSize: 11, fontWeight: 600, letterSpacing: '.02em',
            color: 'var(--warning-text, #92400e)',
            background: 'var(--warning-surface, #fef3c7)',
            border: '1px solid var(--warning-border, #fde68a)',
            padding: '2px 7px', borderRadius: 999,
          }}>Needs recording</span>
        ) : null}>
        {body}
      </EditorBlock>
    );
  }

  Object.assign(window, {
    VideoScriptBlock,
    videoNeedsRecording,
    videoScriptWordCount: wordCount,
    videoScriptSpokenLength: spokenLength,
  });
})();
