// Runtime state + API client. Loaded first so every later module can rely
// on `window.Store` and `window.Api`.

const Store = (() => {
  let state = {
    players: [],
    verifiedSet: new Set(),
    submissions: [],
    me: null,
  };
  const subs = new Set();
  const get = () => state;
  const set = (patch) => {
    state = { ...state, ...patch };
    subs.forEach(fn => fn(state));
  };
  const subscribe = (fn) => { subs.add(fn); return () => subs.delete(fn); };
  return { get, set, subscribe };
})();

const Api = {
  async me() {
    const r = await fetch('/api/me', { credentials: 'include' });
    if (r.status === 401) return null;
    if (!r.ok) throw new Error('me failed');
    return r.json();
  },
  async players() {
    const r = await fetch('/api/players', { credentials: 'include' });
    if (!r.ok) throw new Error('players failed');
    return r.json();
  },
  async submissions() {
    const r = await fetch('/api/submissions', { credentials: 'include' });
    if (!r.ok) throw new Error('submissions failed');
    return r.json();
  },
  async submit(form) {
    const r = await fetch('/api/submissions', { method: 'POST', credentials: 'include', body: form });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'submit failed');
    return r.json();
  },
  async vote(id, vote) {
    const r = await fetch(`/api/submissions/${id}/vote`, {
      method: 'POST', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ vote }),
    });
    if (!r.ok) throw new Error('vote failed');
    return r.json();
  },
  async forceAccept(id) {
    const r = await fetch(`/api/submissions/${id}/force-accept`, { method: 'POST', credentials: 'include' });
    if (!r.ok) throw new Error('force-accept failed');
    return r.json();
  },
  async forceReject(id) {
    const r = await fetch(`/api/submissions/${id}/force-reject`, { method: 'POST', credentials: 'include' });
    if (!r.ok) throw new Error('force-reject failed');
    return r.json();
  },
  async blockUser(submissionId, reason) {
    const r = await fetch(`/api/submissions/${submissionId}/block-user`, {
      method: 'POST', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ reason: reason || null }),
    });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'block-user failed');
    return r.json();
  },
  async deleteSubmission(id) {
    const r = await fetch(`/api/submissions/${id}`, { method: 'DELETE', credentials: 'include' });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'delete failed');
    return r.json();
  },
  async overrideStatus(id, status) {
    const r = await fetch(`/api/submissions/${id}/status`, {
      method: 'POST', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ status }),
    });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'override failed');
    return r.json();
  },
  async editSubmission(id, fields) {
    const r = await fetch(`/api/submissions/${id}`, {
      method: 'PATCH', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(fields),
    });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'edit failed');
    return r.json();
  },
  async regenerateLyrics(id) {
    const r = await fetch(`/api/submissions/${id}/regenerate-lyrics`, {
      method: 'POST', credentials: 'include',
    });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'lyrics regen failed');
    return r.json();
  },
  async regenerateWaveform(id) {
    const r = await fetch(`/api/submissions/${id}/regenerate-waveform`, {
      method: 'POST', credentials: 'include',
    });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'waveform regen failed');
    return r.json();
  },
  artist: {
    async getMe() {
      const r = await fetch('/api/artists/me', { credentials: 'include' });
      if (!r.ok) throw new Error('artist/me failed');
      return r.json();
    },
    // form is a FormData with fields { name, avatar? }.
    async putMe(form) {
      const r = await fetch('/api/artists/me', { method: 'PUT', credentials: 'include', body: form });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'profile save failed');
      return r.json();
    },
  },
  audit: {
    async list({ limit = 200, action, target, since } = {}) {
      const params = new URLSearchParams();
      if (limit)  params.set('limit', limit);
      if (action) params.set('action', action);
      if (target) params.set('target', target);
      if (since)  params.set('since', since);
      const r = await fetch(`/api/audit?${params}`, { credentials: 'include' });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'audit failed');
      return r.json();
    },
  },
  reports: {
    async list() {
      const r = await fetch('/api/reports', { credentials: 'include' });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'reports failed');
      return r.json();
    },
    async dismiss(id) {
      const r = await fetch(`/api/reports/${id}/dismiss`, { method: 'POST', credentials: 'include' });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'dismiss failed');
      return r.json();
    },
    async forceDelete(id) {
      const r = await fetch(`/api/reports/${id}/delete`, { method: 'POST', credentials: 'include' });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'delete failed');
      return r.json();
    },
  },
  async stats() {
    const r = await fetch('/api/stats', { credentials: 'include' });
    if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'stats failed');
    return r.json();
  },
  blocks: {
    async list() {
      const r = await fetch('/api/blocks', { credentials: 'include' });
      if (!r.ok) throw new Error('blocks list failed');
      return r.json();
    },
    async add(identifier, reason, playerName) {
      const r = await fetch('/api/blocks', {
        method: 'POST', credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ identifier, reason: reason || null, playerName: playerName || null }),
      });
      if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'add block failed');
      return r.json();
    },
    async remove(identifier) {
      const r = await fetch(`/api/blocks/${encodeURIComponent(identifier)}`, {
        method: 'DELETE', credentials: 'include',
      });
      if (!r.ok) throw new Error('remove block failed');
      return r.json();
    },
  },
  async logout() {
    await fetch('/auth/logout', { method: 'POST', credentials: 'include' });
  },
};

window.Store = Store;
window.Api = Api;
