
import React, { useState, useCallback, useEffect } from 'react';
import { NotaFiscal, NFStatus, UserRole, HistoryEntry, Fornecedor, GRD, User } from './types';
import Header from './components/Header';
import Dashboard from './components/Dashboard';
import AddNFForm from './components/AddNFForm';
import NFHistoryModal from './components/NFHistoryModal';
import PlusIcon from './components/icons/PlusIcon';
import ConfirmRecebimentoModal from './components/ConfirmRecebimentoModal';
import GerenciarFornecedoresModal from './components/GerenciarFornecedoresModal';
import AnalyticsDashboard from './components/AnalyticsDashboard';
import GenerateGrdModal from './components/GenerateGrdModal';
import GrdView from './components/GrdView';
import CalendarView from './components/CalendarView';
import Login from './components/Login';
import UserManagement from './components/UserManagement';
import ProfilePanel from './components/ProfilePanel';
import { getMe } from './services/users';
import { getGrds, createGrd } from './services/grds';
import { getNFs } from './services/nfs';

const initialNFs: NotaFiscal[] = [
    {
      id: '1',
      numeroNF: '12345',
      numeroPedido: 'PO-001',
      fornecedor: 'Fornecedor Alpha',
      dataEmissao: '2024-07-15',
      dataPrevisao: '2024-07-20',
      status: NFStatus.CONFERIDO,
      dataRecebimento: '2024-07-18',
      dataConferencia: '2024-07-19',
      volumesRecebidos: 10,
      observacao: 'Entrega urgente.',
      history: [
        { status: NFStatus.PENDENTE, date: '2024-07-15T10:00:00Z', user: UserRole.DILIGENCIADOR },
        { status: NFStatus.RECEBIDO, date: '2024-07-18T14:30:00Z', user: UserRole.ALMOXARIFE },
        { status: NFStatus.CONFERIDO, date: '2024-07-19T09:00:00Z', user: UserRole.CONFERENTE },
      ],
    },
    {
      id: '2',
      numeroNF: '67890',
      numeroPedido: 'PO-002',
      fornecedor: 'Fornecedor Beta',
      dataEmissao: '2024-07-16',
      dataPrevisao: '2024-07-22',
      numeroCTE: 'CTE-554433',
      status: NFStatus.RECEBIDO,
      dataRecebimento: '2024-07-21',
      volumesRecebidos: 5,
      history: [
        { status: NFStatus.PENDENTE, date: '2024-07-16T11:00:00Z', user: UserRole.DILIGENCIADOR },
        { status: NFStatus.RECEBIDO, date: '2024-07-21T16:00:00Z', user: UserRole.ALMOXARIFE },
      ],
    },
    {
      id: '3',
      numeroNF: '11223',
      numeroPedido: 'PO-003',
      fornecedor: 'Fornecedor Gama',
      dataEmissao: '2024-07-20',
      dataPrevisao: '2024-07-25',
      status: NFStatus.PENDENTE,
      history: [
        { status: NFStatus.PENDENTE, date: '2024-07-20T08:30:00Z', user: UserRole.DILIGENCIADOR },
      ],
    },
     {
      id: '4',
      numeroNF: '44556',
      numeroPedido: 'PO-004',
      fornecedor: 'Fornecedor Delta',
      dataEmissao: '2024-07-21',
      dataPrevisao: '2024-07-26',
      status: NFStatus.PENDENTE,
      observacao: 'Material frágil, manusear com cuidado.',
      history: [
        { status: NFStatus.PENDENTE, date: '2024-07-21T15:00:00Z', user: UserRole.DILIGENCIADOR },
      ],
    },
];

const getInitialFornecedores = (nfs: NotaFiscal[]): Fornecedor[] => {
    const nomes = new Set(nfs.map(nf => nf.fornecedor));
    return Array.from(nomes)
      .map(nome => ({ id: crypto.randomUUID(), nome }))
      .sort((a,b) => a.nome.localeCompare(b.nome));
};

const loadFromLocalStorage = <T,>(key: string): T | null => {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) as T : null;
  } catch {
    return null;
  }
};

const saveToLocalStorage = (key: string, value: unknown) => {
  try {
    localStorage.setItem(key, JSON.stringify(value));
  } catch {
    // noop
  }
};


function App() {
  const [nfs, setNFs] = useState<NotaFiscal[]>(() => {
    const seeded = loadFromLocalStorage<NotaFiscal[]>('nfs');
    return (seeded && Array.isArray(seeded) && seeded.length > 0)
      ? seeded
      : initialNFs.map(nf => ({...nf, fornecedor: nf.fornecedor.toUpperCase()}));
  });
  const [currentUserRole, setCurrentUserRole] = useState<UserRole>(UserRole.DILIGENCIADOR);
  const [users, setUsers] = useState<User[]>(() => {
    try {
      const raw = localStorage.getItem('users');
      const parsed = raw ? JSON.parse(raw) as User[] : [];
      return Array.isArray(parsed) ? parsed : [];
    } catch { return []; }
  });
  const [currentUser, setCurrentUser] = useState<User | null>(() => {
    try {
      const rawCurrent = localStorage.getItem('currentUser');
      if (rawCurrent) return JSON.parse(rawCurrent) as User;
      const id = localStorage.getItem('currentUserId');
      const raw = localStorage.getItem('users');
      const parsed = raw ? JSON.parse(raw) as User[] : [];
      const found = parsed.find(u => u.id === id) || parsed[0] || null;
      return found || null;
    } catch { return null; }
  });
  const [currentView, setCurrentView] = useState<'list' | 'dashboard' | 'grds' | 'calendar' | 'users'>('list');
  const [authToken, setAuthToken] = useState<string | null>(() => {
    try { return localStorage.getItem('auth_token'); } catch { return null; }
  });
  const [isProfileOpen, setIsProfileOpen] = useState(false);

  const refreshMe = useCallback(async () => {
    if (!authToken) return;
    try {
      const me = await getMe();
      const normalized: User = {
        id: me.id,
        nome: me.nome,
        role: me.role as UserRole,
        email: (me as any).email,
        photo_url: (me as any).photo_url,
      };
      setCurrentUser(normalized);
      try { localStorage.setItem('currentUser', JSON.stringify(normalized)); } catch {}
    } catch {}
  }, [authToken]);

  useEffect(() => { refreshMe(); }, [refreshMe]);
  useEffect(() => { if (!isProfileOpen) { refreshMe(); } }, [isProfileOpen, refreshMe]);
  const [isFormOpen, setIsFormOpen] = useState(false);
  const [viewingNfId, setViewingNfId] = useState<string | null>(null);
  const [confirmingNfId, setConfirmingNfId] = useState<string | null>(null);
  
  const [fornecedores, setFornecedores] = useState<Fornecedor[]>(() => {
    const seeded = loadFromLocalStorage<Fornecedor[]>('fornecedores');
    if (seeded && Array.isArray(seeded) && seeded.length > 0) return seeded;
    const baseNfs = initialNFs.map(nf => ({...nf, fornecedor: nf.fornecedor.toUpperCase()}));
    return getInitialFornecedores(baseNfs);
  });
  const [isGerenciarFornecedoresOpen, setIsGerenciarFornecedoresOpen] = useState(false);

  const [grds, setGrds] = useState<GRD[]>(() => {
    const seeded = loadFromLocalStorage<GRD[]>('grds');
    return (seeded && Array.isArray(seeded)) ? seeded : [];
  });
  const [isGrdModalOpen, setIsGrdModalOpen] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        const serverGrds = await getGrds();
        const mapped: GRD[] = serverGrds.map(g => ({
          id: g.id,
          numeroGRD: Number(g.codigo) || parseInt(g.codigo, 10) || 0,
          dataEmissao: new Date(g.data_emissao).toISOString(),
          nfIds: g.nf_ids,
          observacao: (g.observacao || undefined) as any,
        }));
        setGrds(mapped.sort((a, b) => b.numeroGRD - a.numeroGRD));
      } catch (e) {
        // ignore load error
      }
    })();
  }, []);

  // Carrega NFs do backend para garantir IDs corretos usados nas associações de GRD
  useEffect(() => {
    (async () => {
      try {
        const serverNfs = await getNFs();
        const mapped: NotaFiscal[] = (serverNfs as any[]).map((nf: any) => ({
          id: nf.id,
          numeroNF: nf.numero_nf,
          numeroPedido: nf.numero_pedido,
          fornecedor: (nf.fornecedor_nome || '').toUpperCase(),
          dataPrevisao: nf.data_previsao,
          dataEmissao: nf.data_emissao,
          numeroCTE: nf.numero_cte || undefined,
          observacao: nf.observacao || undefined,
          status: nf.status as NFStatus,
          dataRecebimento: nf.data_recebimento || undefined,
          dataConferencia: nf.data_conferencia || undefined,
          volumesRecebidos: nf.volumes_recebidos || undefined,
          history: [],
        }));
        setNFs(mapped);
      } catch (e) {
        // ignore load error
      }
    })();
  }, []);

  // Seed inicial em localStorage (NFs, fornecedores, GRDs, usuários)
  useEffect(() => {
    const already = localStorage.getItem('seed_initialized');
    if (already) return;

    const seededNfs = nfs.length ? nfs : initialNFs.map(nf => ({...nf, fornecedor: nf.fornecedor.toUpperCase()}));
    const seededFornecedores = fornecedores.length ? fornecedores : getInitialFornecedores(seededNfs);
    const seededGrds = grds.length ? grds : [];
    const users: User[] = [
      { id: crypto.randomUUID(), nome: 'Usuário Master', role: UserRole.MASTER },
      { id: crypto.randomUUID(), nome: 'Usuário Diligenciador', role: UserRole.DILIGENCIADOR },
      { id: crypto.randomUUID(), nome: 'Usuário Almoxarife', role: UserRole.ALMOXARIFE },
      { id: crypto.randomUUID(), nome: 'Usuário Conferente', role: UserRole.CONFERENTE },
    ];

    saveToLocalStorage('nfs', seededNfs);
    saveToLocalStorage('fornecedores', seededFornecedores);
    saveToLocalStorage('grds', seededGrds);
    saveToLocalStorage('users', users);
    setUsers(users);
    setCurrentUser(users[0]);
    setCurrentUserRole(users[0].role);
    localStorage.setItem('currentUserId', users[0].id);
    localStorage.setItem('seed_initialized', 'true');
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Sincroniza alterações com localStorage
  useEffect(() => { saveToLocalStorage('nfs', nfs); }, [nfs]);
  useEffect(() => { saveToLocalStorage('fornecedores', fornecedores); }, [fornecedores]);
  useEffect(() => { saveToLocalStorage('grds', grds); }, [grds]);
  useEffect(() => { saveToLocalStorage('users', users); }, [users]);
  useEffect(() => { if (currentUser) localStorage.setItem('currentUserId', currentUser.id); }, [currentUser]);

  const handleSelectUser = (userId: string) => {
    const user = users.find(u => u.id === userId) || null;
    setCurrentUser(user);
    if (user) setCurrentUserRole(user.role);
  };

  const handleLoggedIn = ({ token, user }: { token: string; user: User }) => {
    setAuthToken(token);
    setCurrentUser(user);
    setCurrentUserRole(user.role);
    setCurrentView('list');
  };

  const handleLogout = useCallback(() => {
    try {
      localStorage.removeItem('auth_token');
      localStorage.removeItem('currentUser');
      localStorage.removeItem('currentUserId');
    } catch {}
    setAuthToken(null);
    setCurrentUser(null);
    setCurrentView('list');
  }, []);


  const handleUpdateStatus = useCallback((id: string, newStatus: NFStatus) => {
    // This handler is now only for CONFERIDO status
    if (newStatus !== NFStatus.CONFERIDO) return;

    setNFs(prevNFs =>
      prevNFs.map(nf => {
        if (nf.id === id) {
          const todayISO = new Date().toISOString();
          const newHistoryEntry: HistoryEntry = {
            status: NFStatus.CONFERIDO,
            date: todayISO,
            user: UserRole.CONFERENTE,
          };
          
          return {
            ...nf,
            status: newStatus,
            dataConferencia: todayISO.split('T')[0],
            history: [...(nf.history || []), newHistoryEntry],
          };
        }
        return nf;
      })
    );
  }, []);

  const handleRequestRecebimento = (id: string) => {
    setConfirmingNfId(id);
  };

  const handleConfirmRecebimento = (volumes: number) => {
    if (!confirmingNfId) return;

    setNFs(prevNFs =>
      prevNFs.map(nf => {
        if (nf.id === confirmingNfId) {
          const todayISO = new Date().toISOString();
          const newHistoryEntry: HistoryEntry = {
            status: NFStatus.RECEBIDO,
            date: todayISO,
            user: UserRole.ALMOXARIFE,
          };
          return {
            ...nf,
            status: NFStatus.RECEBIDO,
            dataRecebimento: todayISO.split('T')[0],
            volumesRecebidos: volumes,
            history: [...nf.history, newHistoryEntry],
          };
        }
        return nf;
      })
    );
    setConfirmingNfId(null);
  };

  const handleAddNF = (newNF: NotaFiscal) => {
    const fornecedorNomeUpper = newNF.fornecedor.trim().toUpperCase();
    
    const finalNF = { ...newNF, fornecedor: fornecedorNomeUpper };
    setNFs(prevNFs => [finalNF, ...prevNFs]);

    const fornecedorExists = fornecedores.some(f => f.nome.toUpperCase() === fornecedorNomeUpper);
    if (!fornecedorExists) {
        handleAddFornecedor(fornecedorNomeUpper);
    }
  };

  const handleShowHistory = (id: string) => {
    setViewingNfId(id);
  };

  const handleCloseHistory = () => {
    setViewingNfId(null);
  };
  
  const selectedNf = nfs.find(nf => nf.id === viewingNfId);

  const handleAddFornecedor = (nome: string) => {
    const nomeTrimmedUpper = nome.trim().toUpperCase();
    if (nomeTrimmedUpper && !fornecedores.some(f => f.nome.toUpperCase() === nomeTrimmedUpper)) {
        const newFornecedor: Fornecedor = { id: crypto.randomUUID(), nome: nomeTrimmedUpper };
        setFornecedores(prev => [...prev, newFornecedor].sort((a,b) => a.nome.localeCompare(b.nome)));
    }
  };

  const handleDeleteFornecedor = (id: string) => {
    setFornecedores(prev => prev.filter(f => f.id !== id));
  };

  const handleEditFornecedor = (id: string, newName: string) => {
    const newNameUpper = newName.trim().toUpperCase();
    const oldFornecedor = fornecedores.find(f => f.id === id);
    if (!oldFornecedor || !newNameUpper) return;

    setFornecedores(prev => prev.map(f => f.id === id ? { ...f, nome: newNameUpper } : f).sort((a,b) => a.nome.localeCompare(b.nome)));
    setNFs(prevNFs => prevNFs.map(nf => nf.fornecedor === oldFornecedor.nome ? { ...nf, fornecedor: newNameUpper } : nf));
  };


  const handleGenerateGrd = async (selectedNfIds: string[], observacao: string) => {
    if (selectedNfIds.length === 0) return;
    try {
      const created = await createGrd({ nfIds: selectedNfIds, observacao: observacao.trim() || undefined });
      const newGrd: GRD = {
        id: created.id,
        numeroGRD: Number(created.codigo) || parseInt(created.codigo, 10) || 0,
        dataEmissao: new Date(created.data_emissao).toISOString(),
        nfIds: created.nf_ids,
        observacao: (created.observacao || undefined) as any,
      };

      setGrds(prev => [newGrd, ...prev].sort((a, b) => b.numeroGRD - a.numeroGRD));

      setNFs(prevNFs => prevNFs.map(nf => {
        if (selectedNfIds.includes(nf.id)) {
          return { ...nf, grdId: newGrd.id, grdNumero: newGrd.numeroGRD };
        }
        return nf;
      }));

      setIsGrdModalOpen(false);
    } catch (err) {
      console.error(err);
      alert('Falha ao gerar GRD no servidor.');
    }
  };


  if (!authToken || !currentUser) {
    return <Login onLoggedIn={handleLoggedIn} />;
  }

  return (
    <div className="min-h-screen bg-primary-dark text-white font-sans">
      <Header 
        currentUserRole={currentUserRole} 
        setCurrentUserRole={setCurrentUserRole}
        users={users}
        currentUser={currentUser}
        onSelectUser={handleSelectUser}
        currentView={currentView}
        setCurrentView={setCurrentView}
        onOpenProfile={() => setIsProfileOpen(true)}
        onLogout={handleLogout}
      />
      <main>
        {currentView === 'list' && (
            <Dashboard nfs={nfs} userRole={currentUserRole} onUpdateStatus={handleUpdateStatus} onRequestRecebimento={handleRequestRecebimento} onShowHistory={handleShowHistory} onOpenGrdModal={() => setIsGrdModalOpen(true)} />
        )}
        {currentView === 'dashboard' && (
            <AnalyticsDashboard nfs={nfs} />
        )}
        {currentView === 'grds' && (
            <GrdView grds={grds} nfs={nfs} />
        )}
        {currentView === 'calendar' && (
            <CalendarView nfs={nfs} onShowHistory={handleShowHistory} />
        )}
        {currentView === 'users' && (
            <UserManagement isMaster={currentUserRole === UserRole.MASTER} />
        )}
      </main>

      {isProfileOpen && (
        <div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50">
          <div className="bg-primary-dark rounded-2xl shadow-xl shadow-primary-dark/50 w-[95%] max-w-3xl p-4 relative">
            <button
              className="absolute top-3 right-3 text-gray-300 hover:text-white"
              onClick={() => setIsProfileOpen(false)}
              aria-label="Fechar"
            >
              ✕
            </button>
            <ProfilePanel />
          </div>
        </div>
      )}
      
      {currentView === 'list' && (currentUserRole === UserRole.DILIGENCIADOR || currentUserRole === UserRole.MASTER) && (
        <button
          onClick={() => setIsFormOpen(true)}
          className="fixed bottom-8 right-8 z-40 bg-primary-light text-primary-dark rounded-full p-4 shadow-lg shadow-primary-light/30 hover:bg-opacity-90 transition-transform duration-200 transform hover:scale-110"
          aria-label="Adicionar Nova NF"
        >
          <PlusIcon className="w-8 h-8" />
        </button>
      )}

      {isFormOpen && (
        <AddNFForm 
            onAdd={handleAddNF} 
            onClose={() => setIsFormOpen(false)} 
            fornecedores={fornecedores} 
            onOpenGerenciarFornecedores={() => setIsGerenciarFornecedoresOpen(true)}
        />
      )}
      {selectedNf && <NFHistoryModal nf={selectedNf} onClose={handleCloseHistory} />}
      {confirmingNfId && (
        <ConfirmRecebimentoModal
          onClose={() => setConfirmingNfId(null)}
          onConfirm={handleConfirmRecebimento}
        />
      )}
      {isGerenciarFornecedoresOpen && (
        <GerenciarFornecedoresModal
            fornecedores={fornecedores}
            onAdd={handleAddFornecedor}
            onDelete={handleDeleteFornecedor}
            onEdit={handleEditFornecedor}
            onClose={() => setIsGerenciarFornecedoresOpen(false)}
        />
      )}
      {isGrdModalOpen && (
        <GenerateGrdModal
            nfs={nfs}
            onClose={() => setIsGrdModalOpen(false)}
            onGenerate={handleGenerateGrd}
        />
      )}
      <footer className="mt-8 py-3 text-center text-xs text-gray-400">
        Versão da aplicação: v2.0.2
      </footer>
    </div>
  );
}

export default App;
