import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { Layout } from './components/Layout';
import { BackupProgress } from './components/BackupProgress';
import { ConfirmProvider } from './components/ConfirmProvider';
import { Dashboard } from './pages/Dashboard';
import { Backups } from './pages/Backups';
import { Restore } from './pages/Restore';
import { Schedule } from './pages/Schedule';
import { Destinations } from './pages/Destinations';
import { Notifications } from './pages/Notifications';
import { Logs } from './pages/Logs';
import { Settings } from './pages/Settings';
import { System } from './pages/System';
import { Migrate } from './pages/Migrate';
import { api, bk } from './lib/api';

export type PageKey = 'dashboard' | 'backups' | 'restore' | 'schedule' | 'destinations' | 'notifications' | 'logs' | 'system' | 'settings' | 'migrate';

interface AppCtx {
  activeBackupId: string | null;
  trackBackup: (id: string) => void;
  navigate: (page: PageKey, opts?: { backupId?: string }) => void;
  restoreTarget: string | null;
  clearRestoreTarget: () => void;
  /** Pre-filter target for the Logs page when navigated to via "View logs" deep-link. */
  logsTarget: string | null;
  clearLogsTarget: () => void;
}
const Ctx = createContext<AppCtx>({
  activeBackupId: null,
  trackBackup: () => {},
  navigate: () => {},
  restoreTarget: null,
  clearRestoreTarget: () => {},
  logsTarget: null,
  clearLogsTarget: () => {},
});
export const useApp = () => useContext(Ctx);

// Pages known to the app. Used to validate the initialPage value coming
// in from class-admin.php — defends against a future submenu slug that
// hasn't been wired to a PageKey yet.
const ALL_PAGES: PageKey[] = [
  'dashboard', 'backups', 'restore', 'schedule', 'destinations',
  'notifications', 'logs', 'system', 'settings', 'migrate',
];

export default function App() {
  // Boot to whichever page the WP admin submenu selected. Falls back to
  // 'dashboard' for unknown slugs.
  const startPage: PageKey =
    (ALL_PAGES as string[]).includes(bk.initialPage)
      ? (bk.initialPage as PageKey)
      : 'dashboard';
  const [page, setPage] = useState<PageKey>(startPage);
  // Per-page nonce bumped every time the user clicks the sidebar / navigates
  // to a given page. Used as a React key on the page component so re-clicking
  // the SAME page (e.g. "Restore" while already on Restore) forces a fresh
  // mount + state reset. Without this, clicking Restore in the sidebar while
  // already on the Restore page is a no-op because React doesn't re-render
  // when setPage is called with the same value — leaving the user stuck on
  // whatever step they were on (post-restore "Done", a half-filled wizard,
  // etc).
  const [pageNonce, setPageNonce] = useState<Record<PageKey, number>>({
    dashboard: 0, backups: 0, restore: 0, schedule: 0, destinations: 0,
    notifications: 0, migrate: 0, logs: 0, system: 0, settings: 0,
  });
  const bumpPage = (k: PageKey) => setPageNonce((n) => ({ ...n, [k]: (n[k] ?? 0) + 1 }));

  // Two separate concerns:
  //   `activeBackupId`: a backup is currently RUNNING. Drives the "Backup
  //                     running…" button label and disables Backup-now.
  //                     Cleared as soon as the backup hits a terminal state.
  //   `panelBackupId`:  which backup the floating progress PANEL should show.
  //                     Stays set until the user dismisses, so they can read
  //                     the final logs after completion.
  const [activeBackupId, setActiveBackupId] = useState<string | null>(null);
  const [panelBackupId,  setPanelBackupId]  = useState<string | null>(null);
  const [refreshKey, setRefreshKey] = useState(0);
  const [restoreTarget, setRestoreTarget] = useState<string | null>(null);
  const [logsTarget,    setLogsTarget]    = useState<string | null>(null);

  useEffect(() => {
    (async () => {
      try {
        const list = await api.backups.list();
        const live = list.items.find((b) => b.status === 'pending' || b.status === 'running');
        if (live) {
          setActiveBackupId(live.id);
          setPanelBackupId(live.id);
        }
      } catch { /* ignore */ }
    })();
  }, []);

  const trackBackup = useCallback((id: string) => {
    setActiveBackupId(id);
    setPanelBackupId(id);
  }, []);

  /** Called by BackupProgress as soon as it observes a terminal status. The
   *  button reverts immediately, but the panel stays open. */
  const onBackupTerminal = useCallback(() => {
    setActiveBackupId(null);
    setRefreshKey((k) => k + 1);
  }, []);

  /** Called when the user dismisses the panel with the × button. */
  const onPanelDismiss = useCallback(() => {
    setPanelBackupId(null);
  }, []);
  const navigate = useCallback((p: PageKey, opts?: { backupId?: string }) => {
    // backupId routes by destination page: Restore page consumes it as
    // restoreTarget, Logs page consumes it as logsTarget. Same arg, different
    // intent — keeps the navigate() signature simple.
    if (opts?.backupId) {
      if      (p === 'restore') setRestoreTarget(opts.backupId);
      else if (p === 'logs')    setLogsTarget(opts.backupId);
    }
    setPage(p);
    bumpPage(p);
  }, []);
  const clearRestoreTarget = useCallback(() => setRestoreTarget(null), []);
  const clearLogsTarget    = useCallback(() => setLogsTarget(null), []);

  // Each page's key combines (a) global refreshKey — bumped on backup-terminal
  // events to force a list refetch — with (b) the per-page nonce that ticks
  // every time the user clicks the same sidebar item again. Combined, the
  // component re-mounts on either signal, giving us a clean reset.
  const k = (p: PageKey) => `${refreshKey}-${pageNonce[p]}`;
  const Page = {
    dashboard:    <Dashboard go={navigate} key={k('dashboard')} />,
    backups:      <Backups                  key={k('backups')} />,
    restore:      <Restore                  key={k('restore')} />,
    schedule:     <Schedule                 key={k('schedule')} />,
    destinations:  <Destinations             key={k('destinations')} />,
    notifications: <Notifications            key={k('notifications')} />,
    migrate:       <Migrate                  key={k('migrate')} />,
    logs:          <Logs                     key={k('logs')} />,
    system:        <System                   key={k('system')} />,
    settings:      <Settings                 key={k('settings')} />,
  }[page];

  return (
    <ConfirmProvider>
      <Ctx.Provider value={{ activeBackupId, trackBackup, navigate, restoreTarget, clearRestoreTarget, logsTarget, clearLogsTarget }}>
        <Layout page={page} setPage={(p) => { setPage(p); bumpPage(p); }}>
          {Page}
        </Layout>
        {panelBackupId && (
          <BackupProgress
            id={panelBackupId}
            onTerminal={onBackupTerminal}
            onDismiss={onPanelDismiss}
          />
        )}
      </Ctx.Provider>
    </ConfirmProvider>
  );
}
