// Optional backend bridge for the static manager prototype.
// If no API/token is available, all methods no-op and the local MVP remains fully usable.

function apiBase() {
  const host = window.location.hostname;
  const fallback = host === 'localhost' || host === '127.0.0.1' || host === ''
    ? 'http://localhost:28080/v1'
    : 'https://backend.carfello.app/v1';
  try {
    const configured = window.AUTOCARE_API_BASE_URL || '';
    const stored = localStorage.getItem('ac.apiBaseUrl') || '';
    const candidate = configured || stored;
    if (candidate && !(!host.includes('localhost') && candidate.includes('localhost'))) {
      return candidate.replace(/\/$/, '');
    }
    return fallback;
  } catch (e) { return fallback; }
}
function demoFallbackAllowed() {
  try {
    const params = new URLSearchParams(window.location.search || '');
    const value = params.get('demoFallback') ?? window.AUTOCARE_ALLOW_DEMO_FALLBACK ?? localStorage.getItem('ac.allowDemoFallback');
    if (value != null) return !['0', 'false', 'no', 'off'].includes(String(value).trim().toLowerCase());
    return ['localhost', '127.0.0.1', ''].includes(window.location.hostname);
  } catch (e) {
    return false;
  }
}
const TOKEN_KEY = 'autocare.tenant.accessToken';
const money = (amount) => ({ amount: Math.round(Number(amount) || 0), currency: 'PLN' });
const moneyFromZl = (amount) => ({ amount: Math.round((Number(amount) || 0) * 100), currency: 'PLN' });
const amount = (m) => m && typeof m.amount === 'number' ? m.amount : 0;
const amountZl = (m) => Math.round(amount(m) / 100);
const roleKey = (role) => String(role || '').toLowerCase().replace(/\s+/g, '_');
const roleLabel = (role) => {
  const key = String(role || '').toLowerCase();
  const labels = { manager: 'Manager', mechanic: 'Mechanic', painter: 'Painter', bodywork: 'Bodywork', pdr: 'PDR', diagnostics: 'Diagnostics' };
  return labels[key] || role || 'Mechanic';
};
const accessKey = (role, access) => access || (roleKey(role) === 'manager' ? 'admin' : 'staff');

function apiToken() {
  try { return localStorage.getItem(TOKEN_KEY) || ''; } catch (e) { return ''; }
}

async function apiFetch(path, options = {}) {
  const token = apiToken();
  if (!token) return null;
  const headers = { 'Content-Type': 'application/json', ...(options.headers || {}), Authorization: `Bearer ${token}` };
  const res = await fetch(`${apiBase()}${path}`, { ...options, headers });
  if (res.status === 204) return {};
  if (!res.ok) throw new Error(`API ${res.status}: ${path}`);
  return res.json();
}

const toUiService = (s) => ({
  id: s.id,
  name: s.name,
  cat: s.category,
  spec: s.specialization,
  net: amount(s.net),
  dur: s.duration,
  active: !!s.active,
});

const toApiService = (s) => ({
  name: s.name,
  category: s.cat,
  specialization: s.spec,
  net: money(s.net),
  duration: s.dur,
  active: !!s.active,
});

const toUiBooking = (b) => ({
  id: b.id,
  customer: b.customerName,
  phone: b.phone,
  guest: !!b.guest,
  vehicle: b.vehicle || {},
  services: b.serviceIds || [],
  slot: b.slot,
  requested: b.requestedAt || '',
  method: b.method,
  verified: !!b.verified,
});

const toUiWorkOrder = (w) => ({
  id: w.id,
  bookingId: w.bookingId,
  customer: w.customerName || w.customer,
  phone: w.phone,
  guest: !!w.guest,
  vehicle: w.vehicle || {},
  services: w.serviceIds || w.services || [],
  assigned: w.assignedIds || w.assigned || [],
  status: w.status,
  method: w.method,
  slot: w.slot,
  opened: w.openedAt || w.opened || '',
  ticketsCount: w.ticketsCount || (w.tickets ? w.tickets.length : 0),
  ticketsApproved: w.ticketsApproved || (w.tickets ? w.tickets.filter((t) => t.status === 'approved').length : 0),
  baseNet: amount(w.total?.base || w.total),
  ticketsNet: amount(w.total?.approvedTickets),
});

const toUiTicket = (t) => ({
  id: t.id,
  type: t.type,
  title: t.title,
  desc: t.description || '',
  author: 'u1',
  net: amount(t.price || t.net),
  status: t.status,
  photos: t.attachmentsComplete ? [{ label: 'attachment' }] : [],
  receipt: t.attachmentsComplete && (t.requiredAttachments || []).includes('receipt') ? { label: 'receipt' } : null,
  chat: [],
});

const toUiSupply = (s) => ({
  id: s.id,
  author: s.authorId || 'u1',
  item: s.item,
  qty: s.qty,
  deadline: s.deadline,
  wo: s.workOrderId || null,
  status: s.status,
  priority: s.priority,
  note: s.note || '',
  orderLink: s.orderLink || '',
});

const toUiTeamMember = (m) => ({
  id: m.id,
  name: m.name,
  email: m.email,
  phone: m.phone,
  role: roleLabel(m.role),
  spec: m.specialization,
  access: m.access,
  active: !!m.active,
  activeOrders: m.activeOrders || 0,
  you: !!m.you,
});

const toUiInvite = (i) => ({
  id: i.id,
  name: i.name,
  phone: i.phone,
  email: i.email,
  role: roleLabel(i.role),
  spec: i.specialization,
  access: i.access,
  pending: i.status === 'sent',
});

const toUiFinanceSummary = (f) => f && ({
  gmv: amount(f.gmv),
  netPayout: amount(f.netPayoutCard),
  cashCollected: amount(f.cashCollected),
  commission: amount(f.commission),
  commissionOwed: amount(f.commissionOwed),
  nextStripePayout: amount(f.nextStripePayout),
  pendingCapture: amount(f.pendingCapture),
  invoiceDueDate: f.invoiceDueDate,
});

const toUiQuoteOffer = (o) => ({
  workshopId: o.workshopId,
  workshopName: o.workshopName,
  rating: o.rating,
  reviews: o.reviews,
  price: amountZl(o.price || o.amount),
  eta: o.eta || o.earliestSlot || '',
  note: o.note || '',
  updated: o.updatedAt || o.updated || 'just now',
});

const toUiQuoteRequest = (q) => ({
  id: q.id,
  customer: q.customerName || q.customer,
  phone: q.phone,
  vehicle: q.vehicle || {},
  title: q.title,
  description: q.description || '',
  location: q.location || q.city || '',
  created: q.createdAt || q.created || '',
  status: q.status || 'open',
  offers: (q.offers || []).map(toUiQuoteOffer).sort((a, b) => a.price - b.price),
});

const AutoCareAPI = {
  enabled: () => !!apiToken(),
  baseUrl: apiBase,

  async login({ baseUrl, email, password }) {
    if (baseUrl) localStorage.setItem('ac.apiBaseUrl', baseUrl.replace(/\/$/, ''));
    const res = await fetch(`${apiBase()}/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ provider: 'email', email, password }),
    });
    if (!res.ok) throw new Error(`Login failed: ${res.status}`);
    const tokens = await res.json();
    localStorage.setItem(TOKEN_KEY, tokens.accessToken);
    return tokens;
  },

  logout() {
    try { localStorage.removeItem(TOKEN_KEY); } catch (e) {}
    toast(tx('Disconnected from backend'), 'logout');
  },

  async hydrateTenantState() {
    if (!apiToken()) return false;
    try {
      const [services, bookings, orders, supply, settings, team, invites, finance, quotes] = await Promise.all([
        apiFetch('/tenant/services'),
        apiFetch('/tenant/bookings?status=pending'),
        apiFetch('/tenant/work-orders'),
        apiFetch('/tenant/supply-requests'),
        apiFetch('/tenant/settings'),
        apiFetch('/tenant/team'),
        apiFetch('/tenant/team/invites'),
        apiFetch('/tenant/finances/summary?period=month'),
        apiFetch('/tenant/quote-requests?status=open').catch(() => null),
      ]);
      if (services) writeStored('ac.services', services.map(toUiService));
      if (bookings) writeStored('ac.bookings', bookings.map(toUiBooking));
      if (orders) writeStored('ac.workOrders', orders.map(toUiWorkOrder));
      if (supply) writeStored('ac.supply', supply.map(toUiSupply));
      if (team) writeStored('ac.team', team.map(toUiTeamMember));
      if (invites) writeStored('ac.team.invites', invites.map(toUiInvite));
      if (finance) writeStored('ac.finance.month', toUiFinanceSummary(finance));
      if (quotes) writeStored('ac.quoteRequests', quotes.map(toUiQuoteRequest));
      if (settings?.profile) {
        writeStored('ac.shopProfile', { ...SHOP, ...settings.profile });
        writeStored('ac.settings.warranty', !!settings.profile.warranty);
        writeStored('ac.settings.warrantyBrands', settings.profile.warrantyBrands || []);
        writeStored('ac.settings.insurance', !!settings.profile.insurance);
        writeStored('ac.settings.insurers', settings.profile.insurers || []);
      }
      toast(tx('Synced with backend'), 'checkCircle');
      return true;
    } catch (e) {
      console.warn('[AutoCareAPI] hydrate failed', e);
      if (demoFallbackAllowed()) toast(tx('Backend unavailable — using local demo data'), 'alert');
      else toast(tx('Backend unavailable — reconnect required'), 'alert');
      return false;
    }
  },

  async saveService(service) {
    if (!apiToken()) return null;
    const payload = toApiService(service);
    const saved = service.id && !String(service.id).startsWith('s')
      ? await apiFetch(`/tenant/services/${service.id}`, { method: 'PATCH', body: JSON.stringify(payload) })
      : await apiFetch('/tenant/services', { method: 'POST', body: JSON.stringify(payload) });
    return saved ? toUiService(saved) : null;
  },

  async setServiceActive(service, active) {
    if (!apiToken()) return null;
    if (!active) {
      await apiFetch(`/tenant/services/${service.id}`, { method: 'DELETE' });
      return { ...service, active: false };
    }
    const saved = await apiFetch(`/tenant/services/${service.id}`, { method: 'PATCH', body: JSON.stringify({ active: true }) });
    return saved ? toUiService(saved) : { ...service, active: true };
  },

  async confirmBooking(booking) {
    if (!apiToken()) return null;
    const order = await apiFetch(`/tenant/bookings/${booking.id}/confirm`, { method: 'POST', body: JSON.stringify({ assigneeIds: [] }) });
    return order ? toUiWorkOrder(order) : null;
  },

  async createSupplyRequest(draft) {
    if (!apiToken()) return null;
    const saved = await apiFetch('/tenant/supply-requests', {
      method: 'POST',
      body: JSON.stringify({
        item: draft.item,
        qty: draft.qty,
        deadline: draft.deadline,
        priority: draft.priority,
        note: draft.note || null,
        workOrderId: draft.wo || null,
      }),
    });
    return saved ? toUiSupply(saved) : null;
  },

  async advanceSupplyRequest(item, status) {
    if (!apiToken()) return null;
    const saved = await apiFetch(`/tenant/supply-requests/${item.id}`, { method: 'PATCH', body: JSON.stringify({ status }) });
    return saved ? toUiSupply(saved) : null;
  },

  async saveSettings({ profile, warranty, brands, insurance, insurers }) {
    if (!apiToken()) return null;
    const [profileResult, capabilityResult] = await Promise.all([
      apiFetch('/tenant/settings/profile', {
        method: 'PATCH',
        body: JSON.stringify({
          name: profile.name,
          phone: profile.phone,
          address: profile.address,
          city: profile.city,
          hours: profile.hours,
          specializations: profile.specializations || SHOP.specializations,
        }),
      }),
      apiFetch('/tenant/settings/capabilities', {
        method: 'PATCH',
        body: JSON.stringify({ warranty, warrantyBrands: brands, insurance, insurers }),
      }),
    ]);
    return capabilityResult || profileResult;
  },

  async inviteMember(input) {
    if (!apiToken()) return null;
    const saved = await apiFetch('/tenant/team/invites', {
      method: 'POST',
      body: JSON.stringify({
        name: input.name,
        phone: input.phone || null,
        email: input.email || null,
        role: roleKey(input.role),
        specialization: input.spec,
        access: accessKey(input.role, input.access),
      }),
    });
    return saved ? toUiInvite(saved) : null;
  },

  async resendInvite(invite) {
    if (!apiToken()) return null;
    await apiFetch(`/tenant/team/invites/${invite.id}/resend`, { method: 'POST' });
    return true;
  },

  async revokeInvite(invite) {
    if (!apiToken()) return null;
    await apiFetch(`/tenant/team/invites/${invite.id}`, { method: 'DELETE' });
    return true;
  },

  async deactivateMember(member) {
    if (!apiToken()) return null;
    await apiFetch(`/tenant/team/${member.id}`, { method: 'DELETE' });
    return true;
  },

  async assignWorkOrder(workOrderId, assigneeIds) {
    if (!apiToken()) return null;
    const order = await apiFetch(`/tenant/work-orders/${workOrderId}/assign`, {
      method: 'POST',
      body: JSON.stringify({ assigneeIds }),
    });
    return order ? toUiWorkOrder(order) : null;
  },

  async createTicket(workOrderId, ticket) {
    if (!apiToken()) return null;
    const saved = await apiFetch(`/tenant/work-orders/${workOrderId}/tickets`, {
      method: 'POST',
      body: JSON.stringify({
        type: ticket.type,
        title: ticket.title,
        description: ticket.desc || null,
        net: money(ticket.net),
      }),
    });
    return saved ? toUiTicket(saved) : null;
  },

  async markReady(workOrderId) {
    if (!apiToken()) return null;
    const order = await apiFetch(`/tenant/work-orders/${workOrderId}/ready`, { method: 'POST' });
    return order ? toUiWorkOrder(order) : null;
  },

  async recordCash(workOrderId, collected) {
    if (!apiToken()) return null;
    await apiFetch(`/tenant/work-orders/${workOrderId}/payment/cash`, {
      method: 'POST',
      body: JSON.stringify({ collected: money(collected) }),
    });
    return true;
  },

  async captureCard(workOrderId) {
    if (!apiToken()) return null;
    await apiFetch(`/tenant/work-orders/${workOrderId}/payment/capture`, { method: 'POST' });
    return true;
  },

  async financeSummary(period) {
    if (!apiToken()) return null;
    const summary = await apiFetch(`/tenant/finances/summary?period=${encodeURIComponent(String(period || 'month').toLowerCase())}`);
    return toUiFinanceSummary(summary);
  },

  async proposeQuoteOffer(request, offer) {
    if (!apiToken()) return null;
    const saved = await apiFetch(`/tenant/quote-requests/${request.id}/offers`, {
      method: 'POST',
      body: JSON.stringify({
        price: moneyFromZl(offer.price),
        earliestSlot: offer.eta,
        note: offer.note || null,
      }),
    });
    return saved ? toUiQuoteOffer(saved) : null;
  },
};

window.AutoCareAPI = AutoCareAPI;
AutoCareAPI.demoFallbackAllowed = demoFallbackAllowed;
AutoCareAPI.strict = () => !demoFallbackAllowed();
