
// Conferencia de Retorno e Status Automatico dos Equipamentos — orcamento 291.
//
// A tela abre com TUDO que saiu no romaneio, ja preenchido. Quem confere so
// diz o que aconteceu com cada item. Sem redigitacao, que era o ponto de a
// ficha de papel virar sistema.
//
// Item com avaria exige FOTO. Sem foto nao salva: "voltou quebrado" sem prova
// vira discussao com o cliente tres semanas depois.
//
// O status fisico do equipamento sai daqui sozinho. "Em acao" NAO e gravado —
// e derivado de romaneio confirmado (ver calcSaldo em Estoque.jsx).

const RETORNO_OPCOES = ['Retornou', 'Retornou com avaria', 'Não retornou'];

const OCORRENCIAS = ['Danificado', 'Sujo', 'Faltando', 'Necessita manutenção', 'Reposição'];

const SITUACAO_FISICA_VARIANT = {
  'Disponível':    'success',
  'Em ação':       'primary',
  'Em manutenção': 'warning',
  'Danificado':    'danger',
  'Extraviado':    'danger',
};

// Quanto mais alto, mais grave: quando o mesmo material aparece em varias
// linhas, o pior resultado e o que fica valendo.
const GRAVIDADE = { 'Disponível': 0, 'Em manutenção': 1, 'Danificado': 2, 'Extraviado': 3 };

// Traducao do que foi conferido para a situacao do equipamento.
// "Sujo" e "Faltando" ficam so registrados na ocorrencia: sujeira nao tira o
// material de circulacao, e faltar peca ja aparece na diferenca enviado x recebido.
function situacaoDoRetorno(linha) {
  if (linha.retorno === 'Não retornou') return 'Extraviado';
  if (linha.retorno === 'Retornou com avaria') {
    if (linha.ocorrencia === 'Danificado') return 'Danificado';
    if (linha.ocorrencia === 'Necessita manutenção' || linha.ocorrencia === 'Reposição') return 'Em manutenção';
  }
  return 'Disponível';
}

// Mesmo bucket e mesmo padrao do upload de foto do material (Estoque.jsx).
async function uploadFotoAvaria(file) {
  const ext = (file.name.split('.').pop() || 'jpg').toLowerCase();
  const path = `avarias/${crypto.randomUUID()}.${ext}`;
  const { error } = await sb.storage.from('event-photos').upload(path, file, { contentType: file.type });
  if (error) throw error;
  const { data: { publicUrl } } = sb.storage.from('event-photos').getPublicUrl(path);
  return publicUrl;
}

function ConferenciaModal({ open, onClose, saida, itens, currentUser, onSaved }) {
  const jaConferido = saida?.status === 'Conferida';

  const [linhas, setLinhas] = React.useState(() => (itens || []).map(i => ({
    id: i.id,
    material_id: i.material_id,
    material_nome: i.material_nome,
    qtd_enviada: i.qtd_enviada || 0,
    estado_saida: i.estado_saida,
    retorno: i.retorno || 'Retornou',
    qtd_recebida: String(i.retorno ? (i.qtd_recebida ?? 0) : (i.qtd_enviada || 0)),
    ocorrencia: i.ocorrencia || '',
    foto_url: i.foto_url || '',
    obs_retorno: i.obs_retorno || '',
  })));

  const [conferente, setConferente] = React.useState(saida?.conferido_por || currentUser?.name || '');
  const [saving, setSaving]         = React.useState(false);
  const [uploading, setUploading]   = React.useState(null); // indice em upload
  const [erro, setErro]             = React.useState(null);

  const setLinha = (idx, campo, valor) => setLinhas(prev => prev.map((l, i) => {
    if (i !== idx) return l;
    const nova = { ...l, [campo]: valor };
    // Trocar o resultado reajusta a quantidade para o caso obvio, mas quem
    // confere ainda pode corrigir na mao.
    if (campo === 'retorno') {
      if (valor === 'Não retornou') nova.qtd_recebida = '0';
      else if (valor === 'Retornou') { nova.qtd_recebida = String(l.qtd_enviada); nova.ocorrencia = ''; }
    }
    return nova;
  }));

  const handleFoto = async (idx, file) => {
    if (!file) return;
    setUploading(idx);
    try {
      const url = await uploadFotoAvaria(file);
      setLinha(idx, 'foto_url', url);
    } catch (err) {
      console.error('[Conferencia.handleFoto] upload falhou:', err);
      setErro('Não foi possível enviar a foto. Tente de novo.');
    }
    setUploading(null);
  };

  const validar = () => {
    for (const l of linhas) {
      const recebida = parseInt(l.qtd_recebida, 10);
      if (Number.isNaN(recebida) || recebida < 0) return `${l.material_nome}: informe a quantidade recebida.`;
      if (recebida > l.qtd_enviada) return `${l.material_nome}: recebido (${recebida}) maior que o enviado (${l.qtd_enviada}).`;
      if (l.retorno === 'Retornou' && recebida !== l.qtd_enviada) {
        return `${l.material_nome}: voltou menos do que saiu. Marque "Retornou com avaria" ou "Não retornou".`;
      }
      if (l.retorno === 'Retornou com avaria') {
        if (!l.ocorrencia) return `${l.material_nome}: escolha a ocorrência da avaria.`;
        if (!l.foto_url)   return `${l.material_nome}: a foto da avaria é obrigatória.`;
      }
    }
    if (!conferente.trim()) return 'Informe quem está conferindo.';
    return null;
  };

  const concluir = async () => {
    const problema = validar();
    if (problema) { setErro(problema); return; }
    setErro(null);
    setSaving(true);

    // 1) grava a conferencia item a item
    for (const l of linhas) {
      const { error } = await sb.from('material_saida_itens').update({
        retorno: l.retorno,
        qtd_recebida: parseInt(l.qtd_recebida, 10) || 0,
        ocorrencia: l.retorno === 'Retornou com avaria' ? (l.ocorrencia || null) : null,
        foto_url: l.foto_url || null,
        obs_retorno: l.obs_retorno?.trim() || null,
      }).eq('id', l.id);
      if (error) {
        console.error('[Conferencia.concluir/item] Supabase error:', error);
        setSaving(false);
        setErro('Erro ao salvar a conferência: ' + (error.message || 'desconhecido'));
        return;
      }
    }

    // 2) status automatico do equipamento — pior resultado por material
    const pior = {};
    linhas.forEach(l => {
      if (!l.material_id) return;
      const s = situacaoDoRetorno(l);
      const atual = pior[l.material_id];
      if (!atual || GRAVIDADE[s] > GRAVIDADE[atual.situacao]) {
        pior[l.material_id] = { situacao: s, linha: l };
      }
    });

    const agora = new Date().toISOString();
    for (const [materialId, info] of Object.entries(pior)) {
      // Retorno normal nao "conserta" material que ja estava com problema por
      // outro motivo: so a liberacao manual na ficha do material faz isso.
      if (info.situacao === 'Disponível') continue;
      const { error } = await sb.from('materiais').update({
        situacao_fisica: info.situacao,
        situacao_obs: [info.linha.ocorrencia, info.linha.obs_retorno].filter(Boolean).join(' — ') || null,
        situacao_alterada_em: agora,
        situacao_alterada_por: conferente.trim(),
      }).eq('id', Number(materialId));
      if (error) console.error('[Conferencia.concluir/material] Supabase error:', error);
    }

    // 3) fecha o romaneio
    const { error: sErr } = await sb.from('material_saidas').update({
      status: 'Conferida',
      conferido_em: agora,
      conferido_por: conferente.trim(),
    }).eq('id', saida.id);

    setSaving(false);
    if (sErr) {
      console.error('[Conferencia.concluir/saida] Supabase error:', sErr);
      setErro('A conferência foi salva, mas o romaneio não fechou: ' + (sErr.message || 'desconhecido'));
      return;
    }
    onSaved();
  };

  const colunas = 'minmax(150px,1fr) 110px 180px 190px';

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={`Conferência de retorno — ${romaneioNumero(saida)}`}
      width={900}
    >
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <div style={{ background: '#F8FAFC', borderRadius: DS.radius.sm, padding: '10px 12px', fontSize: 12, color: DS.colors.textSec }}>
          Saiu em <strong>{romDataHora(saida?.saida_em)}</strong> com {saida?.responsavel_retirada || '—'}.
          {jaConferido && <> Já conferido por <strong>{saida.conferido_por}</strong> em {romDataHora(saida.conferido_em)}.</>}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: colunas, gap: 10, fontSize: 10, fontWeight: 700, color: DS.colors.textMuted, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
          <div>Material</div>
          <div>Enviado × recebido</div>
          <div>Resultado</div>
          <div>Ocorrência / foto</div>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {linhas.map((l, i) => {
            const comAvaria = l.retorno === 'Retornou com avaria';
            return (
              <div key={l.id} style={{
                display: 'grid', gridTemplateColumns: colunas, gap: 10, alignItems: 'start',
                border: `1px solid ${comAvaria ? DS.colors.warning : DS.colors.border}`,
                borderRadius: DS.radius.sm, padding: '10px 12px',
              }}>
                <div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: DS.colors.text }}>{l.material_nome}</div>
                  <div style={{ fontSize: 11, color: DS.colors.textMuted, marginTop: 2 }}>Saiu como {l.estado_saida}</div>
                </div>

                <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ fontSize: 13, fontWeight: 700, color: DS.colors.textSec }}>{l.qtd_enviada}</span>
                  <span style={{ fontSize: 12, color: DS.colors.textMuted }}>×</span>
                  <Input type="number" value={l.qtd_recebida} onChange={v => setLinha(i, 'qtd_recebida', v)} style={{ width: 56 }} />
                </div>

                <Select value={l.retorno} onChange={v => setLinha(i, 'retorno', v)}
                  options={RETORNO_OPCOES.map(o => ({ value: o, label: o }))} />

                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {comAvaria ? (
                    <>
                      <Select value={l.ocorrencia} onChange={v => setLinha(i, 'ocorrencia', v)}
                        options={[{ value: '', label: '— Ocorrência —' }, ...OCORRENCIAS.map(o => ({ value: o, label: o }))]} />
                      {l.foto_url ? (
                        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                          <img src={l.foto_url} alt="Avaria" style={{ width: 40, height: 40, objectFit: 'cover', borderRadius: 6, border: `1px solid ${DS.colors.border}` }} />
                          <Btn size="sm" variant="ghost" icon="trash" onClick={() => setLinha(i, 'foto_url', '')}>Trocar</Btn>
                        </div>
                      ) : (
                        <label style={{ fontSize: 11, color: DS.colors.danger, fontWeight: 600, cursor: 'pointer' }}>
                          {uploading === i ? 'Enviando foto…' : 'Foto obrigatória — escolher'}
                          <input type="file" accept="image/*" style={{ display: 'none' }}
                            onChange={e => handleFoto(i, e.target.files?.[0])} />
                        </label>
                      )}
                    </>
                  ) : (
                    <span style={{ fontSize: 11, color: DS.colors.textMuted }}>—</span>
                  )}
                  <Input value={l.obs_retorno} onChange={v => setLinha(i, 'obs_retorno', v)} placeholder="Observações" />
                </div>
              </div>
            );
          })}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: 12 }}>
          <Input label="Conferido por" value={conferente} onChange={setConferente} placeholder="Quem está recebendo" />
        </div>

        {erro && (
          <div style={{ background: DS.colors.dangerLight, color: DS.colors.danger, borderRadius: DS.radius.sm, padding: '10px 12px', fontSize: 12, fontWeight: 600 }}>
            {erro}
          </div>
        )}

        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <Btn variant="secondary" onClick={onClose}>Fechar</Btn>
          <Btn icon="check" onClick={concluir} disabled={saving || uploading !== null}>
            {saving ? 'Salvando…' : (jaConferido ? 'Salvar correção' : 'Concluir conferência')}
          </Btn>
        </div>
      </div>
    </Modal>
  );
}

Object.assign(window, {
  ConferenciaModal, uploadFotoAvaria, situacaoDoRetorno,
  RETORNO_OPCOES, OCORRENCIAS, SITUACAO_FISICA_VARIANT,
});
