
// ── Supabase Integration Layer ───────────────────────────────────────────────
//
// SETUP INSTRUCTIONS:
// 1. Go to https://supabase.com and create a free project
// 2. In your Supabase dashboard → Settings → API, copy:
//    - Project URL  → paste as SUPABASE_URL below
//    - anon public key → paste as SUPABASE_ANON_KEY below
// 3. Run the SQL setup in your Supabase SQL editor (see bottom of this file)
//
// ─────────────────────────────────────────────────────────────────────────────

const SUPABASE_URL  = 'https://luvpjbcejioxkvjqaxki.supabase.co';
const SUPABASE_ANON_KEY = 'sb_publishable_zSpzjCpH3ZRdNve3sxj0hg_6opwH3MP';

const SUPABASE_CONFIGURED = SUPABASE_URL !== 'YOUR_SUPABASE_URL';

// Minimal Supabase REST client (no SDK needed)
const supa = {
  async _readResponse(response) {
    const payload = await response.json().catch(() => null);
    if (!response.ok) {
      const message = payload?.message || payload?.error_description || payload?.hint || payload?.error || `Supabase request failed with status ${response.status}.`;
      throw new Error(message);
    }
    return payload;
  },

  _headers(extra = {}) {
    return {
      'Content-Type': 'application/json',
      'apikey': SUPABASE_ANON_KEY,
      'Authorization': `Bearer ${(supa._token || SUPABASE_ANON_KEY)}`,
      ...extra,
    };
  },

  _token: null,

  // ── Auth ──────────────────────────────────────────────────────────────────

  async signUp(email, password) {
    const r = await fetch(`${SUPABASE_URL}/auth/v1/signup`, {
      method: 'POST',
      headers: supa._headers(),
      body: JSON.stringify({ email, password }),
    });
    const d = await r.json();
    if (d.access_token) supa._token = d.access_token;
    return d;
  },

  async signIn(email, password) {
    const r = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {
      method: 'POST',
      headers: supa._headers(),
      body: JSON.stringify({ email, password }),
    });
    const d = await r.json();
    if (d.access_token) {
      supa._token = d.access_token;
      localStorage.setItem('sss_token', d.access_token);
      localStorage.setItem('sss_refresh', d.refresh_token || '');
      localStorage.setItem('sss_user', JSON.stringify(d.user));
    }
    return d;
  },

  async signOut() {
    await fetch(`${SUPABASE_URL}/auth/v1/logout`, {
      method: 'POST', headers: supa._headers(),
    }).catch(() => {});
    supa._token = null;
    localStorage.removeItem('sss_token');
    localStorage.removeItem('sss_refresh');
    localStorage.removeItem('sss_user');
  },

  getStoredUser() {
    try {
      const t = localStorage.getItem('sss_token');
      const u = localStorage.getItem('sss_user');
      if (t && u) { supa._token = t; return JSON.parse(u); }
    } catch {}
    return null;
  },

  // ── Database helpers ──────────────────────────────────────────────────────

  async select(table, query = '') {
    const r = await fetch(`${SUPABASE_URL}/rest/v1/${table}?${query}`, {
      headers: supa._headers({ 'Prefer': 'return=representation' }),
    });
    return supa._readResponse(r);
  },

  async insert(table, data) {
    const r = await fetch(`${SUPABASE_URL}/rest/v1/${table}`, {
      method: 'POST',
      headers: supa._headers({ 'Prefer': 'return=representation' }),
      body: JSON.stringify(data),
    });
    return supa._readResponse(r);
  },

  async update(table, data, query) {
    const r = await fetch(`${SUPABASE_URL}/rest/v1/${table}?${query}`, {
      method: 'PATCH',
      headers: supa._headers({ 'Prefer': 'return=representation' }),
      body: JSON.stringify(data),
    });
    return supa._readResponse(r);
  },

  async upsert(table, data) {
    const r = await fetch(`${SUPABASE_URL}/rest/v1/${table}`, {
      method: 'POST',
      headers: supa._headers({ 'Prefer': 'return=representation,resolution=merge-duplicates' }),
      body: JSON.stringify(data),
    });
    return supa._readResponse(r);
  },

  async delete(table, query) {
    const r = await fetch(`${SUPABASE_URL}/rest/v1/${table}?${query}`, {
      method: 'DELETE',
      headers: supa._headers(),
    });
    return r.ok;
  },

  // ── Domain helpers ────────────────────────────────────────────────────────

  async getProfile(userId) {
    const rows = await supa.select('profiles', `id=eq.${userId}`);
    return Array.isArray(rows) ? rows[0] : null;
  },

  async claimCustomerRecords() {
    const token = supa._token || localStorage.getItem('sss_token') || '';
    if (!token) return { ok: false, claimedQuotes: 0, claimedRentals: 0 };
    const response = await fetch('/api/account/claim-records', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`,
      },
    });
    const payload = await response.json().catch(() => ({}));
    if (!response.ok) {
      throw new Error(payload.message || 'Unable to sync account records.');
    }
    return payload;
  },

  async getPricing() {
    const rows = await supa.select('pricing_config', 'order=key.asc');
    if (!Array.isArray(rows) || rows.length === 0) return null;
    const map = {};
    rows.forEach(r => { map[r.key] = r.value; });
    return map;
  },

  async savePricing(configObj) {
    const rows = Object.entries(configObj).map(([key, value]) => ({ key, value: String(value) }));
    return supa.upsert('pricing_config', rows);
  },

  async getQuotes(userId, isAdmin = false) {
    const q = isAdmin ? 'order=created_at.desc' : `user_id=eq.${userId}&order=created_at.desc`;
    return supa.select('quotes', q);
  },

  async saveQuote(quote) {
    return supa.insert('quotes', quote);
  },

  async updateQuote(id, data) {
    return supa.update('quotes', data, `id=eq.${id}`);
  },

  async getRentals(userId, isAdmin = false) {
    const q = isAdmin ? 'order=start_date.desc' : `user_id=eq.${userId}&order=start_date.desc`;
    return supa.select('rentals', q);
  },

  async saveRental(rental) {
    return supa.insert('rentals', rental);
  },

  async updateRental(id, data) {
    return supa.update('rentals', data, `id=eq.${id}`);
  },

  async getAllProfiles() {
    return supa.select('profiles', 'order=created_at.desc');
  },

  async getClientContacts() {
    return supa.select('client_contacts', 'order=updated_at.desc');
  },

  async saveClientContact(contact) {
    return supa.upsert('client_contacts', [contact]);
  },

  // ── Inventory ─────────────────────────────────────────────────────────────

  async getInventory(filters = '') {
    const q = `order=created_at.desc${filters ? '&' + filters : ''}`;
    return supa.select('inventory', q);
  },

  async saveInventoryItem(item) {
    return supa.insert('inventory', item);
  },

  async updateInventoryItem(id, data) {
    return supa.update('inventory', data, `id=eq.${id}`);
  },

  async uploadInventoryPhoto(file) {
    const token = supa._token || localStorage.getItem('sss_token') || '';
    if (!token) {
      throw new Error('Please sign in again before uploading inventory photos.');
    }

    const dataUrl = await new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(String(reader.result || ''));
      reader.onerror = () => reject(new Error('Unable to read the selected file.'));
      reader.readAsDataURL(file);
    });

    const response = await fetch('/api/admin/upload-inventory-photo', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        filename: file?.name || 'inventory-photo',
        contentType: file?.type || 'application/octet-stream',
        dataUrl,
      }),
    });

    const payload = await response.json().catch(() => ({}));
    if (!response.ok || !payload?.url) {
      throw new Error(payload?.message || 'Unable to upload photo.');
    }

    return payload.url;
  },

  async deleteInventoryItem(id) {
    return supa.delete('inventory', `id=eq.${id}`);
  },

  async getProfitSettings() {
    const rows = await supa.select('pricing_config', `key=like.margin*`);
    return Array.isArray(rows) ? rows : [];
  },
};

// ── Mock data for when Supabase is not configured ─────────────────────────────
const MOCK_DATA = {
  pricing: {
    sale_20_new: '2500', sale_20_used: '2000',
    sale_40_new: '4500', sale_40_used: '3200',
    rent_20_new: '120',  rent_20_used: '100',
    rent_40_new: '145',  rent_40_used: '110',
    delivery_flat: '250', delivery_included_miles: '45', delivery_per_mile: '2.50',
    delivery_max_radius: '150', delivery_hub_zip: '98001',
    google_routes_routing_preference: 'TRAFFIC_UNAWARE',
    tax_rate: '0.10', buyout_credit_rate: '0.50',
  },
  quotes: [
    { id: '1', created_at: '2026-04-01', name: 'John Smith', email: 'john@example.com', zip: '98101', interest: 'sale', size: "20'", condition: 'New', status: 'pending', message: 'Need for job site storage' },
    { id: '2', created_at: '2026-04-10', name: 'Lisa Park', email: 'lisa@example.com', zip: '97201', interest: 'rental', size: "40'", condition: 'Used', status: 'quoted', message: 'Long-term storage for farm equipment' },
  ],
  rentals: [
    {
      id: '1', user_id: 'mock', customer_name: 'John Smith',
      customer_email: 'john@example.com',
      container_type: "20' New", monthly_rate: 120,
      start_date: '2026-01-15', status: 'active',
      delivery_cost: 310, container_sale_price: 2500, residual_value: 875,
      notes: 'Delivered to Auburn job site',
    },
  ],
  profiles: [
    { id: 'mock', email: 'john@example.com', full_name: 'John Smith', phone: '(253) 555-0100', is_admin: false, created_at: '2026-01-10' },
  ],
  client_contacts: [
    { email: 'john@example.com', full_name: 'John Smith', phone: '(253) 555-0100', company: 'North Sound Builders', private_notes: 'Prefers text before calls. Usually needs 1-2 day lead time.', created_at: '2026-01-10', updated_at: '2026-04-20' },
  ],
  inventory: [
    {
      id: '1', type: "20' Standard", condition: 'New', color: 'Beige',
      home_zip: '98001', status: 'available', quantity: 3,
      cost: 1800, price: 2500, margin: 28,
      photo_url: 'uploads/20ft-shipping-container-new-beige-side-left.webp',
      notes: 'One-trip, minor scuff on left panel. Ready for delivery.',
      created_at: '2026-03-10',
    },
    {
      id: '2', type: "40' High Cube", condition: 'New', color: 'Beige',
      home_zip: '98001', status: 'available', quantity: 2,
      cost: 3200, price: 4500, margin: 29,
      photo_url: 'uploads/40fthc.jpg',
      notes: 'One-trip. Excellent condition. Doors seal perfectly.',
      created_at: '2026-03-12',
    },
    {
      id: '3', type: "20' Standard", condition: 'Cargo Worthy', color: 'Tan',
      home_zip: '98002', status: 'available', quantity: 1,
      cost: 1100, price: 2000, margin: 45,
      photo_url: 'uploads/Cargo Worthy.jpg',
      notes: 'Some surface rust on top. Doors function well. Great for storage.',
      created_at: '2026-03-15',
    },
    {
      id: '4', type: "40' High Cube", condition: 'Premium Used', color: 'Gray',
      home_zip: '98032', status: 'reserved', quantity: 1,
      cost: 2400, price: 3800, margin: 37,
      photo_url: 'uploads/Premium Used.jpeg',
      notes: 'Minimal rust. Strong floors. Reserved for customer pickup.',
      created_at: '2026-04-01',
    },
    {
      id: '5', type: "20' Standard", condition: 'Wind & Water Tight', color: 'Green',
      home_zip: '98001', status: 'available', quantity: 4,
      cost: 900, price: 1600, margin: 44,
      photo_url: 'uploads/Wind & Water Tight.webp',
      notes: 'Heavier surface rust but structurally solid. Budget option.',
      created_at: '2026-04-05',
    },
    {
      id: '6', type: "40' High Cube", condition: 'Cargo Worthy', color: 'Blue',
      home_zip: '98002', status: 'sold', quantity: 1,
      cost: 2100, price: 3200, margin: 34,
      photo_url: 'uploads/40fthc.jpg',
      notes: 'Sold 4/20/2026. Delivered to Tacoma job site.',
      created_at: '2026-02-20',
    },
  ],
  margin_settings: {
    default_margin: '30',
    min_margin: '15',
    target_margin: '35',
  },
};

// ── SQL Setup Script ──────────────────────────────────────────────────────────
// Run this in your Supabase SQL editor to create all required tables:
//
// -- Profiles (extends auth.users)
// create table public.profiles (
//   id uuid references auth.users(id) primary key,
//   email text, full_name text, phone text,
//   is_admin boolean default false,
//   created_at timestamptz default now()
// );
// alter table public.profiles enable row level security;
// create policy "Users can read own profile" on profiles for select using (auth.uid() = id);
// create policy "Users can update own profile" on profiles for update using (auth.uid() = id);
// create policy "Admins can read all profiles" on profiles for select using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- Lightweight CRM contacts for admin-only notes and contact details
// create table public.client_contacts (
//   email text primary key,
//   full_name text,
//   phone text,
//   company text,
//   private_notes text,
//   created_at timestamptz default now(),
//   updated_at timestamptz default now()
// );
// alter table public.client_contacts enable row level security;
// create policy "Admins full access client contacts" on client_contacts for all using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- Pricing config
// create table public.pricing_config (
//   key text primary key, value text not null, updated_at timestamptz default now()
// );
// alter table public.pricing_config enable row level security;
// create policy "Anyone can read pricing" on pricing_config for select using (true);
// create policy "Admins can update pricing" on pricing_config for all using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- Quotes
// create table public.quotes (
//   id uuid default gen_random_uuid() primary key,
//   user_id uuid references auth.users(id),
//   name text, email text, phone text, zip text,
//   interest text, size text, condition text, delivery text,
//   message text, status text default 'pending',
//   admin_notes text, quoted_price numeric,
//   quote_builder jsonb,
//   created_at timestamptz default now()
// );
// alter table public.quotes enable row level security;
// create policy "Users can read own quotes" on quotes for select using (auth.uid() = user_id);
// create policy "Users can insert quotes" on quotes for insert with check (true);
// create policy "Admins full access quotes" on quotes for all using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- If quotes already exists, add the builder column:
// alter table public.quotes add column if not exists quote_builder jsonb;
//
// -- Rentals
// create table public.rentals (
//   id uuid default gen_random_uuid() primary key,
//   user_id uuid references auth.users(id),
//   customer_name text, customer_email text, container_type text,
//   monthly_rate numeric, start_date date, status text default 'active',
//   delivery_cost numeric, container_sale_price numeric, residual_value numeric,
//   notes text, created_at timestamptz default now()
// );
// alter table public.rentals enable row level security;
// create policy "Users can read own rentals" on rentals for select using (auth.uid() = user_id);
// create policy "Admins full access rentals" on rentals for all using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- Optional but recommended for account linking:
// alter table public.rentals add column if not exists customer_email text;
// create index if not exists quotes_email_idx on public.quotes (lower(email));
// create index if not exists rentals_customer_email_idx on public.rentals (lower(customer_email));
//
// -- Inventory
// create table public.inventory (
//   id uuid default gen_random_uuid() primary key,
//   type text not null,
//   condition text not null,
//   color text,
//   home_zip text,
//   status text default 'available',
//   quantity integer not null default 1,
//   cost numeric not null,
//   price numeric not null,
//   margin numeric generated always as (round((price - cost) / price * 100, 2)) stored,
//   photo_url text,
//   notes text,
//   created_at timestamptz default now(),
//   updated_at timestamptz default now()
// );
// alter table public.inventory enable row level security;
// create policy "Anyone can read available inventory" on inventory for select using (true);
// create policy "Admins full access inventory" on inventory for all using (
//   exists (select 1 from profiles where id = auth.uid() and is_admin = true)
// );
//
// -- If inventory already exists:
// alter table public.inventory add column if not exists quantity integer not null default 1;
//
// -- Auto-create profile on signup
// create or replace function public.handle_new_user()
// returns trigger language plpgsql security definer as $$
// begin
//   insert into public.profiles (id, email)
//   values (new.id, new.email);
//   return new;
// end;
// $$;
// create trigger on_auth_user_created
//   after insert on auth.users
//   for each row execute procedure public.handle_new_user();

Object.assign(window, { supa, SUPABASE_CONFIGURED, MOCK_DATA });
