/* ============================================================
   CASTING — roles, candidates & audition pipeline
   Each role to cast holds a shortlist of talent cards moving through
   a pipeline (requested → self-tape → callback → offer → booked).
   Headshots drop into image-slots. Rolls up roles booked. Persisted.
   ============================================================ */

const CASTING_KEY = 'silverlines.casting.' + (window.PROJ_ID || 'crimson') + '.v1';

const CSTATUS = {
  requested: { label:'Requested', tone:'neutral',  icon:'Mail' },
  selftape:  { label:'Self-tape', tone:'electric', icon:'Video' },
  callback:  { label:'Callback',  tone:'amber',    icon:'PhoneCall' },
  offer:     { label:'Offer out', tone:'amber',    icon:'Send' },
  booked:    { label:'Booked',    tone:'mint',     icon:'CircleCheck' },
  passed:    { label:'Passed',    tone:'neutral',  icon:'CircleSlash' },
};
const CSTATUS_ORDER = ['requested', 'selftape', 'callback', 'offer', 'booked', 'passed'];

const CASTING_SEED = [
  { id:'r1', role:'Lead Pilot — "Crimson"', brief:'Lead. 30s–40s, weathered calm, real flight presence.', candidates:[
    { id:'t1', name:'Lena Frost',   agency:'Apex Talent',   status:'booked',   note:'Director first choice. Wardrobe fitting booked.' },
    { id:'t2', name:'Mara Devlin',  agency:'Stagedoor',     status:'callback', note:'Strong tape — holding as backup.' },
  ]},
  { id:'r2', role:'Ground Crew Chief', brief:'Supporting. 40s–50s, grounded authority, brief dialogue.', candidates:[
    { id:'t3', name:'Sam Okonkwo',  agency:'Northlight',    status:'offer',    note:'Offer out, awaiting agent.' },
    { id:'t4', name:'Reza Mirzaei', agency:'—',             status:'selftape', note:'Self-tape received, reviewing.' },
  ]},
  { id:'r3', role:'Featured Tarmac Crew ×4', brief:'Background featured. Non-speaking, physical, weather-ready.', candidates:[
    { id:'t5', name:'Open call',    agency:'Casting agency', status:'requested', note:'Brief sent to agency for 4 bodies.' },
  ]},
];

function castingLoad() {
  const s = window.SLStore.get(CASTING_KEY); if (Array.isArray(s) && s.length) return s;
  return window.PROJ_BLANK ? [] : CASTING_SEED;
}

function TalentCard({ c, roleId, onPatch, onCycle, onRemove, readOnly }) {
  const st = CSTATUS[c.status] || CSTATUS.requested;
  return (
    <div className="group/tc overflow-hidden rounded-xl border border-line bg-ink-900">
      <div className="relative h-[150px] w-full bg-ink-800">
        <image-slot id={`cast-${roleId}-${c.id}`} placeholder={c.name} shape="rect"
          style={{ position:'absolute', inset:0, width:'100%', height:'100%', color:'rgba(255,255,255,.4)' }}></image-slot>
        <button onClick={() => !readOnly && onCycle()} disabled={readOnly} title="Advance status"
          className="absolute left-2 top-2"><Chip tone={st.tone}><Icon name={st.icon} size={11} />{st.label}</Chip></button>
        {!readOnly && (
          <button onClick={onRemove} title="Remove candidate"
            className="absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-md bg-black/60 text-zinc-300 opacity-0 backdrop-blur-sm transition-opacity hover:text-[#FF6B6B] group-hover/tc:opacity-100"><Icon name="Trash2" size={12} /></button>
        )}
      </div>
      <div className="space-y-1.5 p-2.5">
        <div className="text-[13px] font-700 text-zinc-100"><Edit value={c.name} onChange={v => onPatch({ name: v })} className="text-[13px] font-700" /></div>
        <div className="flex items-center gap-1 text-[11px] text-zinc-500"><Icon name="Briefcase" size={10} /><Edit value={c.agency} onChange={v => onPatch({ agency: v })} className="text-[11px]" /></div>
        <div className="text-[11.5px] text-zinc-400"><Edit value={c.note} onChange={v => onPatch({ note: v })} placeholder="Add a note…" multiline className="text-[11.5px]" /></div>
      </div>
    </div>
  );
}

function CastingModule({ mobile, readOnly = false }) {
  const [roles, setRolesState] = useState(castingLoad);
  const setRoles = next => setRolesState(prev => {
    const v = typeof next === 'function' ? next(prev) : next;
    window.SLStore.set(CASTING_KEY, v);
    return v;
  });

  const booked = roles.filter(r => r.candidates.some(c => c.status === 'booked')).length;
  const totalCands = roles.reduce((a, r) => a + r.candidates.length, 0);

  const patchRole = (rid, p) => setRoles(rs => rs.map(r => r.id === rid ? { ...r, ...p } : r));
  const removeRole = rid => {
    const prev = roles; const role = roles.find(r => r.id === rid) || {};
    setRoles(rs => rs.filter(r => r.id !== rid));
    window.pushUndo && window.pushUndo(`Removed role "${role.role || ''}"`, () => setRoles(prev));
  };
  const addRole = () => setRoles(rs => [...rs, { id:'r' + Date.now(), role:'New role', brief:'', candidates:[] }]);
  const patchCand = (rid, cid, p) => setRoles(rs => rs.map(r => r.id !== rid ? r : { ...r, candidates: r.candidates.map(c => c.id === cid ? { ...c, ...p } : c) }));
  const cycleCand = (rid, cid) => setRoles(rs => rs.map(r => r.id !== rid ? r : { ...r, candidates: r.candidates.map(c => c.id !== cid ? c : { ...c, status: CSTATUS_ORDER[(CSTATUS_ORDER.indexOf(c.status) + 1) % CSTATUS_ORDER.length] }) }));
  const removeCand = (rid, cid) => {
    const prev = roles; const role = roles.find(r => r.id === rid);
    const cand = role && role.candidates.find(c => c.id === cid);
    setRoles(rs => rs.map(r => r.id !== rid ? r : { ...r, candidates: r.candidates.filter(c => c.id !== cid) }));
    window.pushUndo && window.pushUndo(`Removed candidate "${(cand && cand.name) || ''}"`, () => setRoles(prev));
  };
  const addCand = rid => setRoles(rs => rs.map(r => r.id !== rid ? r : { ...r, candidates: [...r.candidates, { id:'t' + Date.now(), name:'New candidate', agency:'—', status:'requested', note:'' }] }));

  return (
    <div className="fade-up">
      {!readOnly && <SectionTitle kicker="Crew & departments · Talent" icon="Drama" title="Casting"
        action={<div className="flex items-center gap-2.5">
          <Chip tone="mint"><Icon name="CircleCheck" size={12} /> {booked}/{roles.length} roles booked</Chip>
          {!readOnly && <button onClick={addRole} className="flex items-center gap-2 rounded-xl bg-cta px-3.5 py-2.5 text-[12.5px] font-700 text-cta-ink transition-colors hover:bg-cta-hover"><Icon name="Plus" size={15} /> Add role</button>}
        </div>} />}

      {roles.length === 0 ? (
        <EmptyState icon="Drama" title="No roles yet"
          sub="Add a role to cast, then start a shortlist of candidates as they self-tape, callback and book."
          action={!readOnly && <button onClick={addRole} className="flex items-center gap-2 rounded-xl bg-cta px-3.5 py-2.5 text-[12.5px] font-700 text-cta-ink transition-colors hover:bg-cta-hover"><Icon name="Plus" size={15} /> Add role</button>} />
      ) : (
      <div className="space-y-5">
        {roles.map(r => {
          const isBooked = r.candidates.some(c => c.status === 'booked');
          return (
            <Panel key={r.id} pad={false} className="overflow-hidden">
              <div className="flex items-start justify-between gap-3 border-b border-line p-3.5">
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-2">
                    <span className={cx('flex h-8 w-8 items-center justify-center rounded-lg', isBooked ? 'bg-mint/15 text-mint' : 'bg-ink-700 text-zinc-300')}><Icon name={isBooked ? 'UserCheck' : 'UserSearch'} size={16} /></span>
                    <div className="text-[14px] font-700 text-zinc-100"><Edit value={r.role} onChange={v => patchRole(r.id, { role: v })} className="text-[14px] font-700" /></div>
                    {isBooked && <Chip tone="mint">Booked</Chip>}
                  </div>
                  <div className="mt-1 pl-10 text-[11.5px] text-zinc-500"><Edit value={r.brief} onChange={v => patchRole(r.id, { brief: v })} placeholder="Casting brief…" multiline className="text-[11.5px]" /></div>
                </div>
                {!readOnly && (
                  <button onClick={() => removeRole(r.id)} title="Remove role"
                    className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-zinc-700 transition-colors hover:bg-[#FF4D6D]/12 hover:text-[#FF4D6D]"><Icon name="Trash2" size={13} /></button>
                )}
              </div>
              <div className={cx('grid gap-3 p-3.5', mobile ? 'grid-cols-2' : 'grid-cols-3 lg:grid-cols-4')}>
                {r.candidates.map(c => (
                  <TalentCard key={c.id} c={c} roleId={r.id} readOnly={readOnly}
                    onPatch={p => patchCand(r.id, c.id, p)} onCycle={() => cycleCand(r.id, c.id)} onRemove={() => removeCand(r.id, c.id)} />
                ))}
                {!readOnly && (
                  <button onClick={() => addCand(r.id)}
                    className="flex min-h-[150px] flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-ink-600 text-zinc-500 transition-colors hover:border-electric/50 hover:text-electric-soft">
                    <Icon name="UserPlus" size={20} /><span className="text-[12px] font-600">Add candidate</span>
                  </button>
                )}
              </div>
            </Panel>
          );
        })}
      </div>
      )}
    </div>
  );
}

window.CastingModule = CastingModule;
