
// App do Promotor — PWA mobile, dentro do proprio PROMO UP 360. Orcamento 290.
//
// O promotor ve SOMENTE as acoes em que esta escalado (RLS da migration 027).
// Confirmar presenca / check-in / check-out passam pelas RPCs da migration 026,
// nunca por UPDATE direto — senao ele conseguiria mudar o proprio cache.
//
// Boa parte do detalhe da acao (traje, briefing, cronograma, endereco
// detalhado) vem do payload do Pedido de Producao (event_reports type='PP'),
// que ja existe no sistema. Por isso nao criamos colunas novas em events.

const fmtPromoMoney = v => 'R$ ' + (parseFloat(v) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

const fmtPromoData = (iso) => {
  if (!iso) return '—';
  const [y, m, d] = String(iso).split('-');
  return (y && m && d) ? `${d}/${m}/${y}` : iso;
};

const fmtPromoDataLonga = (iso) => {
  if (!iso) return '—';
  // 'T00:00:00' evita o deslocamento de um dia por UTC (padrao do projeto).
  return new Date(iso + 'T00:00:00').toLocaleDateString('pt-BR', { weekday: 'long', day: '2-digit', month: 'long' });
};

const fmtPromoHora = iso => iso
  ? new Date(iso).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
  : null;

function PromotorApp({ session, freelancer }) {
  const [escalas, setEscalas] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [abertaId, setAbertaId] = React.useState(null);
  const [toast, setToast] = React.useState(null);
  const showToast = (msg, type = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3000); };

  const carregar = React.useCallback(async () => {
    const { data, error } = await sb
      .from('event_escalas')
      .select('*, events(id, name, client_name, event_date, event_end_date, event_time, location, coordenador_contato, local_lat, local_lng, raio_checkin_metros, resultado_campos)')
      .order('id', { ascending: false });
    if (error) console.error('[PromotorApp.carregar] Supabase error:', error);
    setEscalas(data || []);
    setLoading(false);
  }, []);

  // O topo deste app e escuro, mas o resto do sistema tem barra branca. Sem
  // isto a status bar do Android fica branca colada num cabecalho azul.
  React.useEffect(() => {
    const tag = document.querySelector('meta[name="theme-color"]');
    if (!tag) return;
    const anterior = tag.getAttribute('content');
    tag.setAttribute('content', DS.colors.sidebar);
    return () => tag.setAttribute('content', anterior);
  }, []);

  React.useEffect(() => {
    carregar();
    sb.rpc('promotor_registrar_login').then(() => {});
  }, [carregar]);

  // Proximas primeiro; as sem data vao para o fim.
  const ordenadas = React.useMemo(() => {
    const copia = [...escalas];
    copia.sort((a, b) => {
      const da = a.events?.event_date || '9999-12-31';
      const db = b.events?.event_date || '9999-12-31';
      return da.localeCompare(db);
    });
    return copia;
  }, [escalas]);

  const hojeISO = new Date().toISOString().slice(0, 10);
  const proximas = ordenadas.filter(e => (e.events?.event_date || '9999-12-31') >= hojeISO);
  const passadas = ordenadas.filter(e => (e.events?.event_date || '9999-12-31') < hojeISO).reverse();

  const aberta = escalas.find(e => e.id === abertaId) || null;

  const atualizarEscala = (nova) => setEscalas(prev => prev.map(e => e.id === nova.id ? { ...e, ...nova } : e));

  const handleLogout = () => sb.auth.signOut();

  return (
    <div style={{
      minHeight: '100vh', background: DS.colors.bg, fontFamily: "'Inter', sans-serif",
      paddingBottom: 'calc(24px + env(safe-area-inset-bottom, 0px))',
    }}>
      {/* Topo */}
      <div style={{
        background: DS.colors.sidebar, color: '#fff',
        padding: `calc(18px + env(safe-area-inset-top, 0px)) 16px 16px`,
        position: 'sticky', top: 0, zIndex: 10,
        display: 'flex', alignItems: 'center', gap: 12,
      }}>
        {aberta ? (
          <button onClick={() => setAbertaId(null)}
            style={{ border: 'none', background: 'rgba(255,255,255,0.12)', color: '#fff', width: 34, height: 34, borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}>
            <Icon name="chevronLeft" size={18} color="#fff" />
          </button>
        ) : (
          <Avatar name={freelancer?.name || '?'} size={34} src={freelancer?.photo_url} />
        )}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 15, fontWeight: 800, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {aberta ? 'Detalhe da ação' : `Olá, ${(freelancer?.name || '').split(' ')[0] || 'promotor'}!`}
          </div>
          <div style={{ fontSize: 11, opacity: 0.7, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {aberta ? (aberta.events?.name || '') : 'Suas ações no Promo Up'}
          </div>
        </div>
        <button onClick={handleLogout} title="Sair"
          style={{ border: 'none', background: 'transparent', color: 'rgba(255,255,255,0.7)', padding: 6, cursor: 'pointer', display: 'flex', flexShrink: 0 }}>
          <Icon name="logout" size={18} color="currentColor" />
        </button>
      </div>

      <div style={{ padding: 16, maxWidth: 560, margin: '0 auto' }}>
        {loading ? <Spinner /> : aberta
          ? <DetalheAcao escala={aberta} freelancer={freelancer} onChange={atualizarEscala} showToast={showToast} />
          : (
            <>
              {escalas.length === 0 && (
                <EmptyState icon="calendar" title="Nenhuma ação por enquanto"
                  desc="Quando você for escalado em uma ação, ela aparece aqui." />
              )}

              {proximas.length > 0 && (
                <>
                  <SecaoTitulo>Próximas ações</SecaoTitulo>
                  {proximas.map(e => <CardAcao key={e.id} escala={e} onOpen={() => setAbertaId(e.id)} />)}
                </>
              )}

              {passadas.length > 0 && (
                <>
                  <SecaoTitulo>Ações anteriores</SecaoTitulo>
                  {passadas.map(e => <CardAcao key={e.id} escala={e} onOpen={() => setAbertaId(e.id)} />)}
                </>
              )}
            </>
          )}
      </div>

      {toast && <Toast message={toast.msg} type={toast.type} onClose={() => setToast(null)} />}
    </div>
  );
}

function SecaoTitulo({ children }) {
  return (
    <div style={{ fontSize: 11, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em', margin: '18px 0 10px' }}>
      {children}
    </div>
  );
}

function CardAcao({ escala, onOpen }) {
  const ev = escala.events || {};
  return (
    <Card hover onClick={onOpen} style={{ padding: 16, marginBottom: 10, cursor: 'pointer' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10, marginBottom: 8 }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 15, fontWeight: 800, color: DS.colors.text }}>{ev.name || 'Ação'}</div>
          <div style={{ fontSize: 12, color: DS.colors.textSec, marginTop: 2 }}>{ev.client_name || '—'}</div>
        </div>
        <Badge variant={ESCALA_STATUS_VARIANT[escala.status] || 'default'}>{escala.status}</Badge>
      </div>
      <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', fontSize: 12, color: DS.colors.textSec }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
          <Icon name="calendar" size={13} color={DS.colors.textMuted} />{fmtPromoData(ev.event_date)}
        </span>
        {ev.event_time && (
          <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
            <Icon name="clock" size={13} color={DS.colors.textMuted} />{ev.event_time}
          </span>
        )}
        <span style={{ display: 'flex', alignItems: 'center', gap: 5, fontWeight: 700, color: DS.colors.success }}>
          {fmtPromoMoney(escala.cache)}
        </span>
      </div>
    </Card>
  );
}

// ───────────────────────────────────────────────────────────
// Detalhe da acao + confirmar / check-in / fotos / check-out
// ───────────────────────────────────────────────────────────
function DetalheAcao({ escala, freelancer, onChange, showToast }) {
  const ev = escala.events || {};
  const [pp, setPp] = React.useState(null);
  const [fotos, setFotos] = React.useState([]);
  const [busy, setBusy] = React.useState(false);
  const [fotoOpen, setFotoOpen] = React.useState(false);
  const [resultadosOpen, setResultadosOpen] = React.useState(false);
  const [ocorrenciaOpen, setOcorrenciaOpen] = React.useState(false);
  const [ocorrencias, setOcorrencias] = React.useState([]);
  const [checkinOpen, setCheckinOpen] = React.useState(false);
  const [recusaOpen, setRecusaOpen] = React.useState(false);
  const [motivoRecusa, setMotivoRecusa] = React.useState('');
  const [checkoutOpen, setCheckoutOpen] = React.useState(false);
  const [co, setCo] = React.useState({ realizada: true, houve_problema: false, problema_desc: '', observacao: '', materiais: 'Sim' });
  const [coFoto, setCoFoto] = React.useState(null);
  const [coPreview, setCoPreview] = React.useState('');

  // Supervisor e coordenador enxergam os registros da equipe toda (orcamento 310,
  // item 3). Quem decide de verdade e a policy do banco; isto so muda o filtro.
  const ehSupervisor = escala.funcao === 'Supervisor' || escala.funcao === 'Coordenador';

  React.useEffect(() => {
    if (!ev.id) return;
    sb.from('event_reports').select('payload').eq('event_id', ev.id).eq('type', 'PP').maybeSingle()
      .then(({ data }) => setPp(data?.payload || null));
    const consulta = ehSupervisor
      ? sb.from('escala_fotos').select('*, freelancers(name)').eq('event_id', ev.id)
      : sb.from('escala_fotos').select('*').eq('escala_id', escala.id);
    consulta.order('enviada_em', { ascending: false }).then(({ data }) => setFotos(data || []));

    sb.from('escala_ocorrencias').select('*').eq('escala_id', escala.id)
      .order('criada_em', { ascending: false })
      .then(({ data }) => setOcorrencias(data || []));
  }, [ev.id, escala.id, ehSupervisor]);

  const chamarRpc = async (fn, args, msgOk) => {
    setBusy(true);
    const { data, error } = await sb.rpc(fn, args);
    setBusy(false);
    if (error) {
      console.error(`[DetalheAcao.${fn}] Supabase error:`, error);
      showToast(error.message || 'Não foi possível concluir.', 'danger');
      return null;
    }
    const linha = Array.isArray(data) ? data[0] : data;
    if (linha) onChange(linha);
    showToast(msgOk);
    return linha;
  };

  const confirmarCheckout = async () => {
    // Localizacao no check-out e best-effort: se o GPS falhar o encerramento
    // nao pode travar (a promotora pode ja estar a caminho do transporte). A
    // distancia fica gravada e a producao ve no painel.
    setBusy(true);
    let pos = null;
    try { pos = await obterPosicao(); }
    catch (err) { console.warn('[confirmarCheckout] sem GPS:', err.message); }
    const endereco = pos ? await enderecoAproximado(pos.lat, pos.lng) : null;

    // Foto de encerramento e opcional: se o celular travar na hora de sair, o
    // check-out nao pode ficar preso — a producao ja tem a foto de chegada.
    let fotoUrl = null, fotoPath = null;
    if (coFoto) {
      try {
        const ext = (coFoto.name.split('.').pop() || 'jpg').toLowerCase();
        const caminho = 'checkout_' + escala.id + '/' + crypto.randomUUID() + '.' + ext;
        const { error: upErr } = await sb.storage.from('event-photos').upload(caminho, coFoto, { contentType: coFoto.type });
        if (upErr) throw upErr;
        const { data: pub } = sb.storage.from('event-photos').getPublicUrl(caminho);
        fotoUrl = pub.publicUrl; fotoPath = caminho;
      } catch (err) { console.error('[confirmarCheckout] foto:', err); }
    }

    const ok = await chamarRpc('promotor_check_out', {
      p_escala_id: escala.id,
      p_lat: pos ? pos.lat : null,
      p_lng: pos ? pos.lng : null,
      p_precisao_m: pos ? pos.precisao : null,
      p_endereco: endereco,
      p_realizada: co.realizada,
      p_houve_problema: co.houve_problema,
      p_problema_desc: co.houve_problema ? (co.problema_desc || null) : null,
      p_observacao: co.observacao || null,
      p_materiais: co.materiais || null,
      p_foto_url: fotoUrl,
      p_foto_path: fotoPath,
    }, 'Check-out registrado. Obrigado!');
    if (ok) setCheckoutOpen(false);
  };

  const endereco = [ev.location, pp?.ponto_referencia, pp?.cidade_estado].filter(Boolean).join(' · ');
  const briefing = [pp?.objetivo, pp?.script, pp?.regras].filter(Boolean).join('\n\n');
  const horario = pp?.horario_inicio
    ? `${pp.horario_inicio}${pp.horario_fim ? ' às ' + pp.horario_fim : ''}`
    : (ev.event_time || '—');

  const linhas = [
    { icon: 'crm',       label: 'Cliente',   valor: ev.client_name },
    { icon: 'calendar',  label: 'Data',      valor: fmtPromoDataLonga(ev.event_date) },
    { icon: 'clock',     label: 'Horário',   valor: horario },
    { icon: 'map',       label: 'Endereço',  valor: endereco },
    { icon: 'users',     label: 'Traje',     valor: pp?.dress_code },
    { icon: 'phone',     label: 'Coordenador', valor: ev.coordenador_contato || pp?.equipe?.coordenador?.nome },
    { icon: 'wallet',    label: 'Cachê',     valor: fmtPromoMoney(escala.cache) + (escala.funcao ? ` · ${escala.funcao}` : '') },
    { icon: 'budget',    label: 'Prazo de pagamento', valor: escala.prazo_pagamento },
  ].filter(l => l.valor);

  const jaConfirmou = !!escala.confirmado_em;
  const jaCheckIn   = !!escala.check_in_em;
  const jaCheckOut  = !!escala.check_out_em;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <Card style={{ padding: 16 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10, marginBottom: 12 }}>
          <div style={{ fontSize: 17, fontWeight: 800, color: DS.colors.text }}>{ev.name || 'Ação'}</div>
          <Badge variant={ESCALA_STATUS_VARIANT[escala.status] || 'default'}>{escala.status}</Badge>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          {linhas.map(l => (
            <div key={l.label} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
              <div style={{ width: 28, height: 28, borderRadius: 8, background: '#F1F5F9', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                <Icon name={l.icon} size={14} color={DS.colors.textMuted} />
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{l.label}</div>
                <div style={{ fontSize: 13, color: DS.colors.text, fontWeight: 600, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{l.valor}</div>
              </div>
            </div>
          ))}
        </div>
      </Card>

      {briefing && (
        <Card style={{ padding: 16 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 8 }}>Briefing</div>
          <div style={{ fontSize: 13, color: DS.colors.textSec, lineHeight: 1.6, whiteSpace: 'pre-wrap' }}>{briefing}</div>
        </Card>
      )}

      {/* Acoes */}
      <Card style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>
        {!jaConfirmou && !jaCheckOut && (
          <>
            <Btn size="lg" icon="check" disabled={busy}
              onClick={() => chamarRpc('promotor_confirmar_presenca', { p_escala_id: escala.id }, 'Presença confirmada!')}>
              Confirmar participação
            </Btn>
            <Btn size="lg" variant="secondary" disabled={busy} onClick={() => setRecusaOpen(true)}>
              Não posso participar
            </Btn>
          </>
        )}
        {jaConfirmou && !jaCheckIn && (
          <Btn size="lg" icon="map" disabled={busy} onClick={() => setCheckinOpen(true)}>
            Fazer check-in
          </Btn>
        )}
        {jaCheckIn && !jaCheckOut && (
          <Btn size="lg" variant="success" icon="check" disabled={busy} onClick={() => setCheckoutOpen(true)}>
            Fazer check-out
          </Btn>
        )}
        {/* Abrir localizacao — usa a coordenada cadastrada; se nao houver, cai
            no endereco em texto para o Maps resolver. */}
        {!jaCheckIn && (ev.local_lat != null || endereco) && (
          <Btn variant="secondary" icon="map"
            onClick={() => window.open(ev.local_lat != null
              ? 'https://www.google.com/maps?q=' + ev.local_lat + ',' + ev.local_lng
              : 'https://www.google.com/maps/search/?api=1&query=' + encodeURIComponent(endereco),
              '_blank', 'noopener')}>
            Abrir localização
          </Btn>
        )}

        {jaCheckOut && (
          <div style={{ fontSize: 13, color: DS.colors.success, fontWeight: 700, textAlign: 'center', padding: '6px 0' }}>
            Ação encerrada em {fmtPromoHora(escala.check_out_em)}
          </div>
        )}

        {jaCheckIn && !jaCheckOut && (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
            <Btn variant="secondary" icon="photo" onClick={() => setFotoOpen(true)}>Enviar foto</Btn>
            <Btn variant="secondary" icon="budget" onClick={() => setResultadosOpen(true)}>Resultados</Btn>
          </div>
        )}

        {/* Ocorrencia — secao 14. Continua disponivel depois do check-out:
            problema com material costuma aparecer na hora de devolver. */}
        {jaCheckIn && (
          <Btn variant="danger" icon="alert" onClick={() => setOcorrenciaOpen(true)}>
            Informar ocorrência
          </Btn>
        )}

        {(escala.confirmado_em || escala.check_in_em) && (
          <div style={{ fontSize: 11, color: DS.colors.textMuted, textAlign: 'center' }}>
            {escala.confirmado_em && <>Confirmou {fmtPromoHora(escala.confirmado_em)}</>}
            {escala.check_in_em && <> · Check-in {fmtPromoHora(escala.check_in_em)}</>}
          </div>
        )}
      </Card>

      {/* Prova de chegada — e isto que a producao mostra quando o cliente cobra */}
      {jaCheckIn && (
        <Card style={{ padding: 16 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 10 }}>
            Registro de chegada
          </div>
          <div style={{ display: 'flex', gap: 12 }}>
            {escala.check_in_foto_url && (
              <a href={escala.check_in_foto_url} target={"_blank"} rel={"noreferrer"} style={{ flexShrink: 0 }}>
                <img src={escala.check_in_foto_url} alt={"Foto de chegada"}
                  style={{ width: 76, height: 76, objectFit: 'cover', borderRadius: 10, display: 'block' }} />
              </a>
            )}
            <div style={{ fontSize: 12, color: DS.colors.textSec, lineHeight: 1.7, minWidth: 0 }}>
              <div style={{ fontWeight: 800, color: DS.colors.text }}>
                Check-in {fmtPromoHora(escala.check_in_em)}
              </div>
              {escala.check_in_distancia_m != null && (
                <div>A {fmtDistancia(Number(escala.check_in_distancia_m))} do local da ação</div>
              )}
              {escala.check_in_endereco && (
                <div style={{ wordBreak: 'break-word' }}>{escala.check_in_endereco}</div>
              )}
            </div>
          </div>
        </Card>
      )}

      {/* O promotor precisa ver que a ocorrencia dele foi lida e respondida —
          senao ele deixa de registrar e volta a resolver por telefone. */}
      {ocorrencias.length > 0 && (
        <Card style={{ padding: 16 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 8 }}>
            Ocorrências registradas ({ocorrencias.length})
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {ocorrencias.map(o => (
              <div key={o.id} style={{
                border: '1px solid ' + DS.colors.border, borderRadius: DS.radius.sm, padding: 10,
                borderLeft: '3px solid ' + (o.resolvida_em ? DS.colors.success : DS.colors.danger),
              }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'flex-start' }}>
                  <div style={{ fontSize: 12, fontWeight: 800, color: DS.colors.text }}>{o.categoria}</div>
                  <Badge variant={o.resolvida_em ? 'success' : 'danger'}>
                    {o.resolvida_em ? 'Resolvida' : 'Em aberto'}
                  </Badge>
                </div>
                <div style={{ fontSize: 12, color: DS.colors.textSec, marginTop: 4, whiteSpace: 'pre-wrap' }}>{o.descricao}</div>
                <div style={{ fontSize: 10, color: DS.colors.textMuted, marginTop: 4 }}>{fmtPromoHora(o.criada_em)}</div>
                {o.resposta && (
                  <div style={{ fontSize: 12, color: DS.colors.text, marginTop: 6, background: '#F0FDF4', borderRadius: 6, padding: '6px 8px' }}>
                    <b>Produção:</b> {o.resposta}
                  </div>
                )}
              </div>
            ))}
          </div>
        </Card>
      )}

      {fotos.length > 0 && (
        <Card style={{ padding: 16 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 8 }}>
            {ehSupervisor ? 'Registros da equipe' : 'Fotos enviadas'} ({fotos.length})
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
            {fotos.map(f => (
              <div key={f.id} style={{ minWidth: 0 }}>
                <a href={f.url} target={"_blank"} rel={"noreferrer"}>
                  <img src={f.url} alt={""} style={{ width: '100%', aspectRatio: '1', objectFit: 'cover', borderRadius: 8, display: 'block' }} />
                </a>
                <div style={{ fontSize: 10, fontWeight: 700, color: DS.colors.text, marginTop: 4, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {f.categoria || 'Outros'}
                </div>
                {ehSupervisor && f.freelancers && (
                  <div style={{ fontSize: 10, color: DS.colors.textMuted, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {f.freelancers.name}
                  </div>
                )}
              </div>
            ))}
          </div>
        </Card>
      )}

      <OcorrenciaModal
        open={ocorrenciaOpen}
        escala={escala}
        onClose={() => setOcorrenciaOpen(false)}
        onRegistrada={nova => setOcorrencias(prev => [nova, ...prev])}
        showToast={showToast}
      />

      <EnvioFotoModal
        open={fotoOpen}
        escala={escala}
        freelancer={freelancer}
        onClose={() => setFotoOpen(false)}
        onEnviada={nova => setFotos(prev => [nova, ...prev])}
        showToast={showToast}
      />

      <ResultadosModal
        open={resultadosOpen}
        escala={escala}
        onClose={() => setResultadosOpen(false)}
        onSalvo={onChange}
        showToast={showToast}
      />

      {/* Nao posso participar — secao 5 da especificacao. O motivo e opcional:
          exigir justificativa faz o promotor simplesmente nao responder. */}
      <Modal open={recusaOpen} onClose={() => setRecusaOpen(false)} title="Não posso participar" width={400}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div style={{ fontSize: 13, color: DS.colors.textSec, lineHeight: 1.6 }}>
            A produção será avisada na hora e poderá chamar outro profissional.
          </div>
          <Input label="Motivo (opcional)" value={motivoRecusa} onChange={setMotivoRecusa}
            placeholder="Ex: tenho outro compromisso nesse dia" />
          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
            <Btn variant="secondary" onClick={() => setRecusaOpen(false)}>Voltar</Btn>
            <Btn variant="danger" disabled={busy}
              onClick={async () => {
                const ok = await chamarRpc('promotor_recusar_escala',
                  { p_escala_id: escala.id, p_motivo: motivoRecusa.trim() || null },
                  'Recusa registrada. Obrigado por avisar!');
                if (ok) setRecusaOpen(false);
              }}>
              Confirmar recusa
            </Btn>
          </div>
        </div>
      </Modal>

      <CheckInModal
        open={checkinOpen}
        escala={escala}
        freelancer={freelancer}
        onClose={() => setCheckinOpen(false)}
        onDone={onChange}
        showToast={showToast}
      />

      {/* Check-out — formulario curto */}
      <Modal open={checkoutOpen} onClose={() => setCheckoutOpen(false)} title="Check-out" width={420}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div>
            <div style={{ fontSize: 12, fontWeight: 700, color: DS.colors.textSec, marginBottom: 8 }}>A ação foi realizada?</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
              <Btn variant={co.realizada ? 'success' : 'secondary'} onClick={() => setCo(c => ({ ...c, realizada: true }))}>Sim</Btn>
              <Btn variant={!co.realizada ? 'danger' : 'secondary'} onClick={() => setCo(c => ({ ...c, realizada: false }))}>Não</Btn>
            </div>
          </div>

          <div>
            <div style={{ fontSize: 12, fontWeight: 700, color: DS.colors.textSec, marginBottom: 8 }}>Houve algum problema?</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
              <Btn variant={!co.houve_problema ? 'success' : 'secondary'} onClick={() => setCo(c => ({ ...c, houve_problema: false }))}>Não</Btn>
              <Btn variant={co.houve_problema ? 'danger' : 'secondary'} onClick={() => setCo(c => ({ ...c, houve_problema: true }))}>Sim</Btn>
            </div>
          </div>

          {co.houve_problema && (
            <Input label="Qual foi o problema?" value={co.problema_desc}
              onChange={v => setCo(c => ({ ...c, problema_desc: v }))} placeholder="Descreva rapidamente" />
          )}

          <div>
            <div style={{ fontSize: 12, fontWeight: 700, color: DS.colors.textSec, marginBottom: 8 }}>
              Todos os materiais foram entregues/devolvidos corretamente?
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
              {['Sim', 'Não', 'Não se aplica'].map(op => (
                <Btn key={op} size="sm"
                  variant={co.materiais === op ? (op === 'Não' ? 'danger' : 'success') : 'secondary'}
                  onClick={() => setCo(c => ({ ...c, materiais: op }))}>
                  {op}
                </Btn>
              ))}
            </div>
          </div>

          <div>
            <div style={{ fontSize: 12, fontWeight: 700, color: DS.colors.textSec, marginBottom: 8 }}>
              Foto de encerramento (opcional)
            </div>
            <label style={{
              display: 'block', borderRadius: DS.radius.sm, overflow: 'hidden', cursor: 'pointer',
              border: '1px dashed ' + (coPreview ? 'transparent' : DS.colors.border),
            }}>
              {coPreview ? (
                <img src={coPreview} alt="" style={{ width: '100%', maxHeight: 200, objectFit: 'cover', display: 'block' }} />
              ) : (
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, padding: '16px', fontSize: 13, fontWeight: 600, color: DS.colors.textSec }}>
                  <Icon name="photo" size={16} color={DS.colors.textMuted} />
                  Tirar foto do encerramento
                </div>
              )}
              <input type="file" accept="image/*" capture="environment"
                onChange={e => {
                  const f = e.target.files && e.target.files[0];
                  if (f) { if (coPreview) URL.revokeObjectURL(coPreview); setCoFoto(f); setCoPreview(URL.createObjectURL(f)); }
                  e.target.value = '';
                }}
                style={{ display: 'none' }} />
            </label>
          </div>

          <Input label="Observação (opcional)" value={co.observacao}
            onChange={v => setCo(c => ({ ...c, observacao: v }))} placeholder="Algo que a produção precisa saber" />

          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
            <Btn variant="secondary" onClick={() => setCheckoutOpen(false)}>Cancelar</Btn>
            <Btn icon="check" onClick={confirmarCheckout} disabled={busy}>{busy ? 'Enviando…' : 'Encerrar ação'}</Btn>
          </div>
        </div>
      </Modal>
    </div>
  );
}

Object.assign(window, { PromotorApp });
