import React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';
import { Challenge, Team, Solve, CTFState, BlogPost } from './types';
import { api } from './services/api';

interface CTFContextType {
  state: CTFState;
  currentUser: Team | null;
  login: (name: string, pass: string) => Promise<boolean>;
  register: (name: string, pass: string) => Promise<void>;
  logout: () => void;
  submitFlag: (challengeId: string, flag: string) => Promise<boolean>;
  toggleCtf: () => Promise<void>;
  resetScores: () => Promise<void>;
  upsertChallenge: (data: FormData, id?: string) => Promise<void>;
  deleteChallenge: (id: string) => Promise<void>;
  deleteAllChallenges: () => Promise<void>;
  exportChallenges: () => Promise<{ challenges: any[] }>;
  importChallenges: (file: File) => Promise<void>;
  backupDatabase: () => Promise<any>;
  restoreDatabase: (file: File) => Promise<void>;
  updateTeam: (id: string, data: any) => Promise<void>;
  updateProfile: (password?: string) => Promise<void>;
  deleteTeam: (id: string) => Promise<void>;
  createBlogPost: (data: { title: string, content: string }) => Promise<void>;
  updateBlogPost: (id: string, data: { title: string, content: string }) => Promise<void>;
  deleteBlogPost: (id: string) => Promise<void>;
  updateConfig: (formData: FormData) => Promise<void>;
  refreshState: () => Promise<void>;
  loading: boolean;
  loadError: string | null;
}

const CTFContext = createContext<CTFContextType | null>(null);

export const useCTF = () => {
  const context = useContext(CTFContext);
  if (!context) throw new Error('useCTF must be used within provider');
  return context;
};

export const CTFProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [state, setState] = useState<CTFState>({ isStarted: false, startTime: null, teams: [], challenges: [], solves: [], blogs: [], config: {} });
  const [currentUser, setCurrentUser] = useState<Team | null>(null);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);

  // Fix: Removed return value to match refreshState: () => Promise<void> interface
  const refreshState = useCallback(async () => { 
    try { 
      const newState = await api.getState(); 
      setState(newState); 
    } catch (err: any) {
      console.error("State refresh failed:", err);
      throw err;
    } 
  }, []);

  useEffect(() => { 
    const init = async () => { 
      const session = localStorage.getItem('hip6_session'); 
      if (session) { try { const { team } = JSON.parse(session); setCurrentUser(team); } catch (e) {} } 
      
      const safetyTimeout = setTimeout(() => {
        setLoading(false);
        setLoadError("CONNECTION_TIMED_OUT: RETRYING...");
      }, 6000);

      try {
        await refreshState(); 
        setLoadError(null);
      } catch (err: any) {
        setLoadError("COMMUNICATION_FAULT: RECONNECTING...");
      } finally {
        clearTimeout(safetyTimeout);
        setLoading(false); 
      }
    }; 
    init(); 
    const interval = setInterval(() => {
      refreshState().catch(() => {});
    }, 30000); 
    return () => clearInterval(interval); 
  }, [refreshState]);

  const login = async (n: string, p: string) => { try { const { team, token } = await api.login(n, p); localStorage.setItem('hip6_session', JSON.stringify({ team, token })); setCurrentUser(team); await refreshState(); return true; } catch (e) { return false; } };
  const register = async (n: string, p: string) => { const { team, token } = await api.register(n, p); localStorage.setItem('hip6_session', JSON.stringify({ team, token })); setCurrentUser(team); await refreshState(); };
  const logout = () => { localStorage.removeItem('hip6_session'); setCurrentUser(null); };
  const submitFlag = async (cid: string, f: string) => { const res = await api.submitFlag(cid, f); await refreshState(); return res.success; };
  const toggleCtf = async () => { await api.toggleCtf(); await refreshState(); };
  const resetScores = async () => { if (window.confirm("Reset all scores to 0?")) { await api.resetScores(); await refreshState(); }};
  const upsertChallenge = async (d: FormData, id?: string) => { await api.upsertChallenge(d, id); await refreshState(); };
  const deleteChallenge = async (id: string) => { if (window.confirm("DELETE_CHALLENGE?")) { await api.deleteChallenge(id); await refreshState(); } };
  const deleteAllChallenges = async () => { if (window.confirm("Delete all challenges?")) {await api.deleteAllChallenges(); await refreshState(); }};
  const exportChallenges = async () => await api.exportChallenges();
  const importChallenges = async (f: File) => { await api.importChallenges(f); await refreshState(); };
  const backupDatabase = async () => await api.backupDatabase();
  const restoreDatabase = async (f: File) => await api.restoreDatabase(f);
  const updateTeam = async (id: string, d: any) => { await api.updateTeam(id, d); await refreshState(); };
  const updateProfile = async (p?: string) => { await api.updateProfile({ password: p }); await refreshState(); };
  const deleteTeam = async (id: string) => { if (window.confirm("EXPEL_OPERATOR?")) { await api.deleteTeam(id); await refreshState(); } };
  const createBlogPost = async (d: any) => { await api.createBlogPost(d); await refreshState(); };
  const updateBlogPost = async (id: string, d: any) => { await api.updateBlogPost(id, d); await refreshState(); };
  const deleteBlogPost = async (id: string) => { await api.deleteBlogPost(id); await refreshState(); };
  const updateConfig = async (d: FormData) => { await api.updateConfig(d); await refreshState(); };

  return (
    <CTFContext.Provider value={{ 
      state, currentUser, login, register, logout, submitFlag, toggleCtf, resetScores, 
      upsertChallenge, deleteChallenge, deleteAllChallenges, exportChallenges, 
      importChallenges, backupDatabase, restoreDatabase, updateTeam, updateProfile, 
      deleteTeam, createBlogPost, updateBlogPost, deleteBlogPost, updateConfig, 
      refreshState, loading, loadError 
    }}>
      {children}
    </CTFContext.Provider>
  );
};