// Module-level caches — persist across modal open/close without re-fetching.
let _repoCache = null
const _branchCache = {}

async function fetchBranches(repo) {
  if (!repo) return []
  if (_branchCache[repo]) return _branchCache[repo]
  const r = await fetch(`/api/branches?repo=${encodeURIComponent(repo)}`)
  const data = await r.json()
  if (!r.ok) return []
  _branchCache[repo] = data
  return data
}

function ConfigModal({ open, onClose, config, onSave }) {
  const [draft, setDraft]           = React.useState(config)
  const [commonRepos, setCommonR]   = React.useState([])
  const [activityRepos, setActR]    = React.useState([])
  const [commonBranches, setCommonB] = React.useState([])
  const [actBranches, setActB]      = React.useState([])
  const [fetchErr, setFetchErr]     = React.useState(null)
  const [fetching, setFetching]     = React.useState(false)

  // Sync draft when config prop changes (e.g. initial load)
  React.useEffect(() => { setDraft(config) }, [config, open])

  // Fetch repo list on open (uses cache after first load)
  React.useEffect(() => {
    if (!open) return
    if (_repoCache) {
      setCommonR(_repoCache.commonRepos)
      setActR(_repoCache.activityRepos)
      return
    }
    setFetching(true)
    setFetchErr(null)
    fetch('/api/repos')
      .then(r => r.json())
      .then(data => {
        if (data.error) throw new Error(data.error)
        _repoCache = data
        setCommonR(data.commonRepos || [])
        setActR(data.activityRepos || [])
      })
      .catch(err => setFetchErr(err.message))
      .finally(() => setFetching(false))
  }, [open])

  // Fetch branches when common repo changes
  React.useEffect(() => {
    if (!draft.commonRepo) { setCommonB([]); return }
    fetchBranches(draft.commonRepo).then(setCommonB)
  }, [draft.commonRepo])

  // Fetch branches when activity repo changes
  React.useEffect(() => {
    if (!draft.activityRepo) { setActB([]); return }
    fetchBranches(draft.activityRepo).then(setActB)
  }, [draft.activityRepo])

  // Auto-save whenever draft is complete
  React.useEffect(() => {
    if (draft.commonRepo && draft.activityRepo) onSave(draft)
  }, [draft])

  if (!open) return null

  // Extract product-line prefix: "corp-ais/sky-fbb-onboarding-common" → "fbb"
  function prefixOf(repo) {
    const m = (repo || '').match(/sky-(mpo|fbb|iot|cciid)-onboarding-common/)
    return m ? m[1] : null
  }

  const prefix = prefixOf(draft.commonRepo)
  const filteredActivity = prefix
    ? activityRepos.filter(r => {
        const name = r.split('/')[1]
        return name.startsWith(`sky-${prefix}`) && name.endsWith('-onboarding-activity')
      })
    : activityRepos

  function update(k, v) { setDraft(d => ({ ...d, [k]: v })) }

  function handleCommonChange(e) {
    const val = e.target.value
    // Reset activity if prefix no longer matches
    const newPrefix = prefixOf(val)
    const actName = (draft.activityRepo || '').split('/')[1] || ''
    const actStillValid = newPrefix && actName.startsWith(`sky-${newPrefix}`)
    setDraft(d => ({
      ...d,
      commonRepo:   val,
      activityRepo: actStillValid ? d.activityRepo : '',
    }))
  }

  return (
    <div className="pv-scrim" onClick={onClose} data-screen-label="Config modal">
      <div className="pv-modal" onClick={e => e.stopPropagation()} role="dialog" aria-labelledby="cfg-title">
        <div className="pv-modal-head">
          <h2 id="cfg-title">Config</h2>
          <button className="pv-modal-close" onClick={onClose} aria-label="Close">
            <Icon name="x" />
          </button>
        </div>

        <div className="pv-modal-body">
          {fetching && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--fg-3)', fontSize: 13 }}>
              <div className="pv-spinner" style={{ width: 14, height: 14 }} />
              Loading repos…
            </div>
          )}
          {fetchErr && (
            <div style={{ color: 'var(--danger-600)', fontSize: 12 }}>
              Failed to load repos: {fetchErr}
            </div>
          )}

          <div className="pv-modal-section-label">Common</div>

          <Field label="Common Repo">
            <Select value={draft.commonRepo} onChange={handleCommonChange} disabled={fetching}>
              <option value="">— select —</option>
              {commonRepos.map(r => <option key={r} value={r}>{r.split('/')[1]}</option>)}
            </Select>
          </Field>

          <Field label="Common Branch">
            <Select
              value={draft.commonBranch}
              onChange={e => update('commonBranch', e.target.value)}
              disabled={!draft.commonRepo || commonBranches.length === 0}
            >
              {commonBranches.length === 0 && <option value={draft.commonBranch}>{draft.commonBranch || 'develop'}</option>}
              {commonBranches.map(b => <option key={b} value={b}>{b}</option>)}
            </Select>
          </Field>

          <hr className="pv-modal-divider" />

          <div className="pv-modal-section-label">Activity</div>

          <Field label="Activity Repo">
            <Select
              value={draft.activityRepo}
              onChange={e => update('activityRepo', e.target.value)}
              disabled={fetching || !draft.commonRepo}
            >
              <option value="">— select common first —</option>
              {filteredActivity.map(r => <option key={r} value={r}>{r.split('/')[1]}</option>)}
            </Select>
          </Field>

          <Field label="Activity Branch">
            <Select
              value={draft.activityBranch}
              onChange={e => update('activityBranch', e.target.value)}
              disabled={!draft.activityRepo || actBranches.length === 0}
            >
              {actBranches.length === 0 && <option value={draft.activityBranch}>{draft.activityBranch || 'develop'}</option>}
              {actBranches.map(b => <option key={b} value={b}>{b}</option>)}
            </Select>
          </Field>

        </div>
      </div>
    </div>
  )
}

Object.assign(window, { ConfigModal })
