// Dashy — main app (API-backed)

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "accent": "#2A6FDB",
  "density": "cozy",
  "showTags": true
}/*EDITMODE-END*/;

const ACCENTS = ['#2A6FDB', '#1F8A5B', '#D97757', '#7A5AF8'];

function useApiData(authed) {
  const [data, setData] = React.useState({ tasks: [], users: [], audit: [] });
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    if (!authed) return;
    
    let mounted = true;
    const load = async () => {
      try {
        const [tasks, users, audit] = await Promise.all([
          api.getTasks(),
          api.getUsers(),
          api.getAudit()
        ]);
        if (mounted) {
          setData({ tasks, users, audit });
          setLoading(false);
        }
      } catch (e) {
        console.error("Failed to load data:", e);
      }
    };

    load();
    const off = api.subscribe(load);
    return () => { mounted = false; off(); };
  }, [authed]);

  return { ...data, loading };
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [authed, setAuthed] = React.useState(!!api.token);
  // Optional: Decode token to get meId if needed, but for prototype we just assume rod if not known yet, 
  // or decode JWT using a simple base64 parse.
  const [meId, setMeId] = React.useState(() => {
    if (api.token) {
      try {
        return JSON.parse(atob(api.token.split('.')[1])).sub;
      } catch(e) {}
    }
    return 'rod';
  });

  const { tasks, users: dbUsers, audit, loading } = useApiData(authed);
  const [tab, setTab] = React.useState('overview');
  const [adding, setAdding] = React.useState(null);
  const [openTaskId, setOpenTaskId] = React.useState(null);
  const [showLogs, setShowLogs] = React.useState(false);
  const [showSettings, setShowSettings] = React.useState(false);
  
  const [headsUp, setHeadsUp] = React.useState([
    { id: 'h1', kind: 'unsuccessful', taskId: 't7',
      title: 'WO #2188 auto-marked Unsuccessful',
      sub: 'Two missed bookings — assigned to Kirra for review' },
    { id: 'h2', kind: 'billing', taskId: 't4',
      title: 'Form response switched to Billing',
      sub: 'K. Wynne · originally Service Booking' },
  ]);

  if (!authed) {
    return <LoginScreen onLogin={async (id, pwd = "password123") => {
      try {
        await api.login(id, pwd);
        setMeId(id);
        setAuthed(true);
        // Fire & forget audit log
        api.addAudit({ actor: id, action: 'login', summary: 'Signed in' }).catch(console.error);
      } catch (e) {
        alert("Login failed: " + e.message);
      }
    }} />;
  }

  if (loading) return <BootSplash />;

  const userMap = Object.fromEntries(dbUsers.map(u => [u.id, u]));
  const merge = (id) => {
    const base = findUser(id); 
    if (!base && !userMap[id]) return null;
    const live = userMap[id] || {};
    if (!base) {
      return { id, name: live.name, role: live.role, hue: live.hue, initials: live.initials,
               photo: live.photo || null, account_type: live.account_type || 'standard' };
    }
    return { ...base, name: live.name || base.name, role: live.role || base.role,
             photo: live.photo || null, account_type: live.account_type || 'standard' };
  };
  const me = merge(meId) || merge('rod');
  const isAdmin = me && me.account_type === 'admin';
  const openTask = tasks.find(x => x.id === openTaskId);

  const addTask = async ({ title, description, assignee, priority }) => {
    try {
      const t = await api.createTask({
        title, description, assignee_id: assignee, priority,
        added_by: meId, source: 'manual', status: 'open', tags: []
      });
      await api.addAudit({
        actor: meId, action: 'task_created',
        summary: 'Created task "' + title + '" for ' + (merge(assignee)||{}).name,
        target: t.id
      });
      setAdding(null);
    } catch(e) {
      console.error(e);
      alert("Failed to create task");
    }
  };

  const moveTask = async (taskId, toUserId) => {
    try {
      await api.updateTask(taskId, { assignee_id: toUserId });
      await api.addAudit({ actor: meId, action: 'task_moved', summary: 'Moved task to ' + (merge(toUserId)||{}).name, target: taskId });
    } catch(e) {}
  };

  const setPriority = async (taskId, p) => {
    try {
      await api.updateTask(taskId, { priority: p });
    } catch(e) {}
  };

  const completeTask = async (taskId) => {
    try {
      await api.updateTask(taskId, { status: 'closed' });
      await api.addAudit({ actor: meId, action: 'task_completed', summary: 'Marked task as completed', target: taskId });
      setOpenTaskId(null);
    } catch(e) {
      console.error(e);
      alert("Failed to complete task: " + e.message);
    }
  };

  const reopenTask = async (taskId) => {
    try {
      await api.updateTask(taskId, { status: 'open' });
      await api.addAudit({ actor: meId, action: 'task_reopened', summary: 'Reopened task', target: taskId });
      setOpenTaskId(null);
    } catch(e) {
      console.error(e);
      alert("Failed to reopen task: " + e.message);
    }
  };

  const dismissHU = (id) => setHeadsUp(h => h.filter(x => x.id !== id));
  const openTaskFromAnywhere = (id) => { setOpenTaskId(id); setShowLogs(false); };

  // Map API fields to frontend component expectations
  const frontendTasks = tasks.map(t => ({
    ...t,
    assignee: t.assignee_id,
    addedBy: t.added_by,
    addedAt: t.added_at,
    tags: t.tags.map(tagObj => tagObj.tag)
  }));

  const frontendAudit = audit.map(a => ({
    ...a,
    actor: a.actor,
    action: a.action,
    summary: a.summary,
    target: a.target,
    at: a.at
  }));

  const mappedOpenTask = frontendTasks.find(x => x.id === openTaskId);

  return (
    <div className="app">
      <TopBar
        me={me}
        isAdmin={isAdmin}
        tab={tab}
        setTab={setTab}
        onAdd={() => setAdding(meId)}
        onLogs={() => setShowLogs(true)}
        onProfile={() => setShowSettings(true)}
      />

      <HeadsUp items={headsUp} onDismiss={dismissHU} onOpenTask={openTaskFromAnywhere} />

      <main className="main">
        {tab === 'overview' && (
          <OverviewScreen
            tasks={frontendTasks} density={t.density}
            onOpen={(task) => setOpenTaskId(task.id)}
            onAddFor={(uid) => setAdding(uid)}
            onMoveTask={moveTask}
          />
        )}
        {tab !== 'overview' && (
          <UserScreen
            user={merge(tab)} tasks={frontendTasks} density={t.density}
            onOpen={(task) => setOpenTaskId(task.id)}
            onAddFor={(uid) => setAdding(uid)}
          />
        )}
      </main>

      <AddTaskModal open={!!adding} onClose={() => setAdding(null)} onSubmit={addTask} defaultAssignee={adding} me={me} />
      {mappedOpenTask && (
        <TaskDetail task={mappedOpenTask} allAudit={frontendAudit} onClose={() => setOpenTaskId(null)} onMove={moveTask} onPriority={setPriority} onComplete={() => completeTask(mappedOpenTask.id)} onReopen={() => reopenTask(mappedOpenTask.id)} />
      )}
      {showLogs && (
        <Modal title="Audit log" onClose={() => setShowLogs(false)} wide>
          <AuditScreen entries={frontendAudit} onOpen={openTaskFromAnywhere} />
        </Modal>
      )}
      {showSettings && (
        <SettingsScreen
          user={me}
          dbUsers={dbUsers}
          isAdmin={isAdmin}
          onClose={() => setShowSettings(false)}
          onSave={async (edits) => {
            // Not implemented on backend yet for user updating, mock success
            setShowSettings(false);
          }}
          onLogout={() => { 
            api.logout(); 
            setAuthed(false); 
            setShowSettings(false); 
          }}
          onSwitchUser={async (id) => { 
            try {
              await api.login(id, "password123");
              setMeId(id);
              setShowSettings(false);
            } catch(e) {
              alert("Failed to switch user");
            }
          }}
        />
      )}

      <DashyTweaks t={t} setTweak={setTweak} />
    </div>
  );
}

function BootSplash() {
  return (
    <div className="boot">
      <div className="boot__pulse" />
      <div className="boot__label mono">loading from API…</div>
    </div>
  );
}

function DashyTweaks({ t, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Appearance">
        <TweakRadio label="Theme" value={t.theme}
          options={[{value:'light',label:'Light'},{value:'dark',label:'Dark'}]}
          onChange={v => setTweak('theme', v)} />
        <TweakColor label="Accent" value={t.accent} options={ACCENTS} onChange={v => setTweak('accent', v)} />
        <TweakRadio label="Density" value={t.density}
          options={[{value:'compact',label:'Compact'},{value:'cozy',label:'Cozy'}]}
          onChange={v => setTweak('density', v)} />
        <TweakToggle label="Show tags on cards" value={t.showTags} onChange={v => setTweak('showTags', v)} />
      </TweakSection>
    </TweaksPanel>
  );
}

function ThemeBridge() {
  const [t] = useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => {
    document.documentElement.dataset.theme = t.theme;
    document.documentElement.style.setProperty('--accent', t.accent);
    document.documentElement.dataset.showTags = t.showTags ? 'on' : 'off';
  }, [t.theme, t.accent, t.showTags]);
  return null;
}

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