// Main App component
const { useState: useStateApp, useEffect: useEffectApp, useRef: useRefApp } = React;

const API_BASE = '';

// API key storage
const API_KEY_STORAGE_KEY = 'clio_api_key';

function getStoredApiKey() {
  return localStorage.getItem(API_KEY_STORAGE_KEY);
}

function setStoredApiKey(key) {
  localStorage.setItem(API_KEY_STORAGE_KEY, key);
}

function clearStoredApiKey() {
  localStorage.removeItem(API_KEY_STORAGE_KEY);
}

// Authenticated fetch wrapper
async function authFetch(url, options = {}) {
  const apiKey = getStoredApiKey();
  const headers = {
    ...options.headers,
    'X-API-Key': apiKey || '',
  };
  const response = await fetch(url, { ...options, headers });
  if (response.status === 401) {
    clearStoredApiKey();
    window.dispatchEvent(new Event('auth-required'));
  }
  return response;
}

// Parse hash into route info
function parseHash() {
  const hash = window.location.hash.slice(1) || '/dashboard';
  const parts = hash.split('/').filter(Boolean);

  if (parts[0] === 'recording' && parts[1]) {
    return { view: 'detail', recordingId: parseInt(parts[1], 10) };
  }
  if (parts[0] === 'calendar' && parts[1]) {
    return { view: 'calendar', day: parts[1] };
  }

  const validViews = ['dashboard', 'calendar', 'search', 'highlights'];
  const view = validViews.includes(parts[0]) ? parts[0] : 'dashboard';
  return { view };
}

// Build hash from route info
function buildHash(view, options = {}) {
  if (view === 'detail' && options.recordingId) {
    return `#/recording/${options.recordingId}`;
  }
  if (view === 'calendar' && options.day) {
    return `#/calendar/${options.day}`;
  }
  return `#/${view}`;
}

// Transform API recording to frontend format
function transformRecording(rec) {
  const startTime = new Date(rec.recorded_at);
  const durationMinutes = (rec.duration || 0) / 60;
  const endTime = new Date(startTime.getTime() + durationMinutes * 60 * 1000);

  return {
    id: rec.id,
    source: rec.source_name,
    quality: 'good', // API doesn't track quality, default to good
    durationMinutes,
    startTime,
    endTime,
    fileSizeMB: rec.file_size_bytes ? Math.round(rec.file_size_bytes / 1024 / 1024) : Math.round(durationMinutes * 0.9),
    transcript: (rec.segments || []).map(s => ({
      id: `${rec.id}-seg-${s.id}`,
      startSeconds: s.start_time,
      endSeconds: s.end_time,
      text: s.text,
      confidence: s.confidence || 0.9,
    })),
    hasTranscript: (rec.segments || []).length > 0,
    highlights: (rec.highlights || []).map(h => ({
      id: `h-${h.id}`,
      recordingId: h.recording_id,
      segmentId: h.segment_id,
      startSeconds: h.start_seconds,
      endSeconds: h.end_seconds || null,
      tag: h.tag,
      note: h.note || '',
      createdAt: new Date(h.created_at),
    })),
    sampleRate: rec.sample_rate || 44100,
    bitDepth: rec.bit_depth || 16,
    peakDB: -30,
    audioPath: rec.audio_path,
  };
}

function ApiKeyPrompt({ onSubmit }) {
  const [key, setKey] = useStateApp('');
  const [error, setError] = useStateApp(null);
  const [checking, setChecking] = useStateApp(false);

  async function handleSubmit(e) {
    e.preventDefault();
    if (!key.trim()) return;

    setChecking(true);
    setError(null);

    try {
      // Test the key by making a simple request
      const res = await fetch(`${API_BASE}/api/v1/sources`, {
        headers: { 'X-API-Key': key.trim() }
      });

      if (res.status === 401) {
        setError('Invalid API key');
        setChecking(false);
        return;
      }

      if (!res.ok) {
        setError('Server error');
        setChecking(false);
        return;
      }

      setStoredApiKey(key.trim());
      onSubmit();
    } catch (err) {
      setError('Connection failed');
      setChecking(false);
    }
  }

  return (
    <div style={{
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      height: '100vh', background: 'var(--bg)',
    }}>
      <form onSubmit={handleSubmit} style={{
        background: 'var(--bg2)', padding: 32, borderRadius: 8,
        border: '1px solid var(--border)', width: 320,
      }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 14, marginBottom: 20, color: 'var(--text)' }}>
          Enter API Key
        </div>
        <input
          type="password"
          value={key}
          onChange={(e) => setKey(e.target.value)}
          placeholder="API Key"
          autoFocus
          style={{
            width: '100%', padding: '10px 12px', marginBottom: 12,
            background: 'var(--bg3)', border: '1px solid var(--border)',
            borderRadius: 4, color: 'var(--text)', fontFamily: 'var(--font-mono)',
            fontSize: 13, outline: 'none',
          }}
        />
        {error && (
          <div style={{ color: 'var(--red)', fontSize: 12, marginBottom: 12, fontFamily: 'var(--font-mono)' }}>
            {error}
          </div>
        )}
        <button
          type="submit"
          disabled={checking}
          style={{
            width: '100%', padding: '10px 12px',
            background: 'var(--amber)', color: 'var(--bg)',
            border: 'none', borderRadius: 4, fontFamily: 'var(--font-mono)',
            fontSize: 12, fontWeight: 600, cursor: 'pointer',
            opacity: checking ? 0.6 : 1,
          }}
        >
          {checking ? 'Checking...' : 'Continue'}
        </button>
      </form>
    </div>
  );
}

function App() {
  const [data, setData] = useStateApp({ recordings: [], highlights: [], devices: {} });
  const [loading, setLoading] = useStateApp(true);
  const [error, setError] = useStateApp(null);
  const [needsAuth, setNeedsAuth] = useStateApp(!getStoredApiKey());

  // Lift highlights state so adding/removing works across views
  const [highlights, setHighlights] = useStateApp([]);

  // Listen for auth-required events (401 responses)
  useEffectApp(() => {
    function handleAuthRequired() {
      setNeedsAuth(true);
    }
    window.addEventListener('auth-required', handleAuthRequired);
    return () => window.removeEventListener('auth-required', handleAuthRequired);
  }, []);

  // Initialize from URL hash
  const initialRoute = parseHash();
  const [view, setViewState] = useStateApp(initialRoute.view);
  const [selectedDay, setSelectedDayState] = useStateApp(initialRoute.day || null);
  const [selectedRecording, setSelectedRecording] = useStateApp(null);
  const [loadingDetail, setLoadingDetail] = useStateApp(false);
  const [initialSeekTime, setInitialSeekTime] = useStateApp(null);

  // Track if we should skip pushing to history (for popstate handling)
  const skipHistoryPush = useRefApp(false);

  // Update URL when view changes
  function setView(newView) {
    setViewState(newView);
    if (newView !== 'detail') {
      setSelectedRecording(null);
    }
    if (!skipHistoryPush.current) {
      const hash = buildHash(newView, { day: selectedDay });
      if (window.location.hash !== hash) {
        window.history.pushState(null, '', hash);
      }
    }
  }

  // Update URL when selected day changes
  function setSelectedDay(day) {
    setSelectedDayState(day);
    if (view === 'calendar' && !skipHistoryPush.current) {
      const hash = buildHash('calendar', { day });
      if (window.location.hash !== hash) {
        window.history.pushState(null, '', hash);
      }
    }
  }

  // Set initial hash if empty
  useEffectApp(() => {
    if (!window.location.hash) {
      window.history.replaceState(null, '', '#/dashboard');
    }
  }, []);

  // Handle browser back/forward
  useEffectApp(() => {
    function handlePopState() {
      skipHistoryPush.current = true;
      const route = parseHash();
      setViewState(route.view);
      if (route.day) {
        setSelectedDayState(route.day);
      }
      if (route.view === 'detail' && route.recordingId) {
        fetchRecordingDetail(route.recordingId);
      } else {
        setSelectedRecording(null);
      }
      skipHistoryPush.current = false;
    }

    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, []);

  // Fetch full recording details (with transcript) when selecting a recording
  async function fetchRecordingDetail(recordingId) {
    setLoadingDetail(true);
    try {
      const res = await authFetch(`${API_BASE}/api/v1/recordings/${recordingId}`);
      if (!res.ok) throw new Error('Failed to fetch recording');
      const rec = await res.json();
      const transformed = transformRecording(rec);

      // Update the recording in our data
      setData(prev => ({
        ...prev,
        recordings: prev.recordings.map(r =>
          r.id === recordingId ? transformed : r
        ),
      }));

      setSelectedRecording(transformed);
    } catch (err) {
      console.error('Failed to fetch recording detail:', err);
    } finally {
      setLoadingDetail(false);
    }
  }

  // Wrapper to select recording and fetch its details
  // Optional seekTime to jump to a specific position (e.g., from highlights)
  function selectRecording(rec, seekTime = null) {
    if (rec && rec.id) {
      setInitialSeekTime(seekTime);
      fetchRecordingDetail(rec.id);
      setViewState('detail');
      if (!skipHistoryPush.current) {
        const hash = buildHash('detail', { recordingId: rec.id });
        window.history.pushState(null, '', hash);
      }
    } else {
      setSelectedRecording(null);
      setInitialSeekTime(null);
    }
  }

  // Fetch data from API
  useEffectApp(() => {
    async function fetchData() {
      try {
        const [recordingsRes, sourcesRes, highlightsRes] = await Promise.all([
          authFetch(`${API_BASE}/api/v1/recordings?limit=1000`),
          authFetch(`${API_BASE}/api/v1/sources`),
          authFetch(`${API_BASE}/api/v1/highlights?limit=1000`),
        ]);

        if (!recordingsRes.ok) throw new Error('Failed to fetch recordings');

        const recordingsData = await recordingsRes.json();
        const sourcesData = await sourcesRes.json();
        const highlightsData = await highlightsRes.json();

        // Transform recordings
        const recordings = recordingsData.recordings.map(transformRecording);

        // Transform sources to devices format
        const devices = {};
        for (const src of sourcesData.sources || []) {
          devices[src.source_name] = {
            name: src.source_name.charAt(0).toUpperCase() + src.source_name.slice(1),
            lastSeen: src.last_recording ? new Date(src.last_recording) : new Date(),
            model: src.source_name,
            totalRecordings: src.recording_count,
            totalHours: src.total_hours || 0,
          };
        }

        // Transform highlights
        const allHighlights = (highlightsData.highlights || []).map(h => ({
          id: `h-${h.id}`,
          recordingId: h.recording_id,
          segmentId: h.segment_id,
          startSeconds: h.start_seconds,
          endSeconds: h.end_seconds || null,
          tag: h.tag,
          note: h.note || '',
          createdAt: new Date(h.created_at),
        }));

        setData({ recordings, highlights: allHighlights, devices });
        setHighlights(allHighlights);

        // Handle initial URL route
        const route = parseHash();

        // Set selected day from URL or default to most recent
        if (route.day) {
          setSelectedDayState(route.day);
        } else if (recordings.length > 0) {
          const sorted = [...recordings].sort((a, b) => b.startTime - a.startTime);
          setSelectedDayState(sorted[0].startTime.toISOString().slice(0, 10));
        }

        // If URL has a recording ID, fetch it
        if (route.view === 'detail' && route.recordingId) {
          fetchRecordingDetail(route.recordingId);
        }

        setLoading(false);
      } catch (err) {
        console.error('Failed to fetch data:', err);
        setError(err.message);
        setLoading(false);
      }
    }
    fetchData();
  }, []);

  // Show API key prompt if not authenticated
  if (needsAuth) {
    return (
      <ApiKeyPrompt onSubmit={() => {
        setNeedsAuth(false);
        setLoading(true);
        // Re-trigger data fetch by incrementing a counter or similar
        // For simplicity, just reload the page
        window.location.reload();
      }} />
    );
  }

  if (loading) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', color: 'var(--text2)' }}>
        Loading recordings...
      </div>
    );
  }

  if (error) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', color: 'var(--red)' }}>
        Error: {error}
      </div>
    );
  }

  // navigateTo is now just an alias for setView (which handles URL updates)
  const navigateTo = setView;

  // Augment data with live highlights
  const liveData = {
    ...data,
    highlights,
    recordings: data.recordings.map(r => ({
      ...r,
      highlights: highlights.filter(h => h.recordingId === r.id),
    })),
  };

  return (
    <div style={{ display: 'flex', height: '100vh', overflow: 'hidden' }}>
      <Sidebar view={view === 'detail' ? '_detail' : view} setView={navigateTo} data={liveData} />

      <main style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        {/* Top bar */}
        <div style={{
          height: 40, flexShrink: 0, borderBottom: '1px solid var(--border)',
          background: 'var(--bg2)', display: 'flex', alignItems: 'center',
          padding: '0 20px', gap: 12,
        }}>
          {view === 'detail' && selectedRecording && (
            <button onClick={() => setView('calendar')} style={{ color: 'var(--text3)', fontSize: 12, fontFamily: 'var(--font-mono)' }}>
              ‹ {selectedRecording.startTime.toLocaleDateString([], { month: 'short', day: 'numeric' })}
            </button>
          )}
          <div style={{ flex: 1 }} />
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text3)' }}>
            {new Date().toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' })}
          </div>
        </div>

        {/* View content */}
        <div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
          {view === 'dashboard' && (
            <Dashboard
              data={liveData}
              setView={navigateTo}
              setSelectedDay={setSelectedDay}
              setSelectedRecording={selectRecording}
            />
          )}
          {view === 'calendar' && (
            <DayView
              data={liveData}
              selectedDay={selectedDay}
              setSelectedDay={setSelectedDay}
              setSelectedRecording={selectRecording}
              setView={navigateTo}
            />
          )}
          {view === 'search' && (
            <SearchView
              data={liveData}
              setSelectedRecording={selectRecording}
              setView={navigateTo}
            />
          )}
          {view === 'highlights' && (
            <HighlightsView
              data={liveData}
              highlights={highlights}
              setSelectedRecording={selectRecording}
              setView={navigateTo}
            />
          )}
          {loadingDetail && (
            <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', color: 'var(--text2)' }}>
              Loading recording...
            </div>
          )}
          {view === 'detail' && selectedRecording && !loadingDetail && (
            <RecordingDetail
              recording={liveData.recordings.find(r => r.id === selectedRecording.id) || selectedRecording}
              data={liveData}
              onBack={() => setView('calendar')}
              allHighlights={highlights}
              setAllHighlights={setHighlights}
              initialSeekTime={initialSeekTime}
              onSeekHandled={() => setInitialSeekTime(null)}
            />
          )}
        </div>
      </main>
    </div>
  );
}

// Export utilities for other components
Object.assign(window, { authFetch, getStoredApiKey });

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
