// client-state.jsx — Client portal data, scoped to ONE railroad customer.
// When Supabase is live, loads real jobs and invoices from the database.
// Falls back to prototype static data when Supabase is unavailable.

const { createContext, useContext, useState, useMemo, useCallback, useEffect } = React;

const C_money = (n) => (n < 0 ? '-$' : '$') + Math.abs(+n || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const C_num = (n, d = 1) => (+n || 0).toLocaleString('en-US', { minimumFractionDigits: d, maximumFractionDigits: d });
const C_date = (iso) => iso ? new Date(iso.length === 10 ? iso + 'T00:00' : iso).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—';

// Static prototype data (fallback when Supabase is unavailable)
const CLIENTS = {
  'cli-bnsf': { id: 'cli-bnsf', name: 'BNSF Railway',       railroad: 'BNSF', billRate: 92.50, terms: 'Net 30', logo: 'BNSF' },
  'cli-uprr': { id: 'cli-uprr', name: 'Union Pacific',      railroad: 'UPRR', billRate: 89.00, terms: 'Net 30', logo: 'UP' },
  'cli-csx':  { id: 'cli-csx',  name: 'CSX Transportation', railroad: 'CSX',  billRate: 94.00, terms: 'Net 45', logo: 'CSX' },
};

// Static job data (shown while Supabase loads or as fallback)
const ALL_JOBS = [
  { id: 'JOB-24179', clientId: 'cli-bnsf', projectNumber: 'N-0224.3.014.02', name: 'Mainline Tie Renewal — Cascade Sub', sub: 'Cascade Sub', mp: '142.3 – 143.1', state: 'WA', start: '2026-05-04', end: '2026-06-12', status: 'active', rwics: [{ name: 'Marcus Hale', badge: 'FLG-2241', cert: 'current', onsite: true }, { name: 'Diana Russo', badge: 'FLG-1907', cert: 'current', onsite: true }] },
  { id: 'JOB-24166', clientId: 'cli-bnsf', projectNumber: 'N-0224.3.001.07', name: 'Stampede Sub Welding', sub: 'Stampede', mp: '67.4 – 69.0', state: 'WA', start: '2026-05-08', end: '2026-06-30', status: 'active', rwics: [{ name: 'Tomás Beltrán', badge: 'FLG-3025', cert: 'expired', onsite: true }] },
  { id: 'JOB-24155', clientId: 'cli-bnsf', projectNumber: 'N-0411.6.008.01', name: 'Hi-Line Curve Resurfacing', sub: 'Hi-Line', mp: '1110.4 – 1112.0', state: 'MT', start: '2026-04-29', end: '2026-05-30', status: 'wrapping', rwics: [{ name: 'Jaylen Brooks', badge: 'FLG-4488', cert: 'current', onsite: false }] },
  { id: 'JOB-24201', clientId: 'cli-uprr', projectNumber: 'U-1188.4.022.03', name: 'Feather River Bridge Repair', sub: 'Feather River', mp: '198.0 – 198.3', state: 'CA', start: '2026-05-15', end: '2026-07-30', status: 'active', rwics: [{ name: 'Priya Anand', badge: 'FLG-5512', cert: 'current', onsite: true }] },
  { id: 'JOB-24210', clientId: 'cli-uprr', projectNumber: 'U-2030.1.005.11', name: 'Salt Lake Tie Replacement', sub: 'Lynndyl', mp: '744.1 – 745.2', state: 'UT', start: '2026-05-18', end: '2026-06-22', status: 'active', rwics: [{ name: 'Anita Sokolov', badge: 'FLG-7733', cert: 'expiring', onsite: true }] },
  { id: 'JOB-24225', clientId: 'cli-csx',  projectNumber: 'C-1502.1.030.02', name: 'Cumberland Sub Crossing Replace', sub: 'Cumberland', mp: '142.0 – 142.4', state: 'MD', start: '2026-05-20', end: '2026-07-04', status: 'starting', rwics: [] },
];

const ALL_INVOICES = [
  { id: 'INV-2042', clientId: 'cli-bnsf', job: 'JOB-24179', period: '2026-05-04 — 2026-05-17', hours: 214.5, amount: 19841.25, status: 'paid', due: '2026-06-16', issued: '2026-05-18' },
  { id: 'INV-2051', clientId: 'cli-bnsf', job: 'JOB-24166', period: '2026-05-08 — 2026-05-17', hours: 96.0, amount: 8880.00, status: 'sent', due: '2026-06-20', issued: '2026-05-19' },
  { id: 'INV-2055', clientId: 'cli-bnsf', job: 'JOB-24179', period: '2026-05-18 — 2026-05-31', hours: 188.2, amount: 17408.50, status: 'draft', due: '2026-06-30', issued: '2026-05-31' },
  { id: 'INV-2048', clientId: 'cli-uprr', job: 'JOB-24201', period: '2026-05-15 — 2026-05-29', hours: 142.0, amount: 12638.00, status: 'sent', due: '2026-06-28', issued: '2026-05-30' },
  { id: 'INV-2031', clientId: 'cli-csx',  job: 'JOB-24225', period: '2026-05-20 — 2026-05-31', hours: 0, amount: 0, status: 'draft', due: '2026-07-04', issued: '2026-05-31' },
];

// Normalize a Supabase job row to the client portal shape
function normalizeJob(row, clientId) {
  return {
    id: row.job_number || row.id,
    clientId: clientId,
    projectNumber: row.job_number || '',
    name: row.name || row.location || '',
    sub: row.subdivision || '',
    mp: '',
    state: row.state || '',
    start: row.start_date || '',
    end: row.end_date || '',
    status: row.status || 'active',
    rwics: [],
    _dbId: row.id,
  };
}

// Normalize a Supabase invoice row to the client portal shape
function normalizeInvoice(row, clientId) {
  return {
    id: row.invoice_number || row.id,
    clientId: clientId,
    job: row.job_id || '',
    period: [row.invoice_date, row.due_date].filter(Boolean).join(' — '),
    hours: (row.line_items || []).reduce((s, li) => s + (li.hours || 0), 0),
    amount: row.total || 0,
    status: row.status || 'draft',
    due: row.due_date || '',
    issued: row.invoice_date || '',
    _dbId: row.id,
  };
}

const ClientCtx = createContext(null);

function ClientProvider({ children }) {
  const [session, setSession] = useState(() => {
    try { const s = RFP.session(); return (s && s.app === 'client') ? s : null; } catch (e) { return null; }
  });
  const clientId = session && session.clientId;
  const client = clientId ? CLIENTS[clientId] : null;

  // Live data from Supabase (null = not loaded yet, [] = loaded empty)
  const [liveJobs, setLiveJobs] = useState(null);
  const [liveInvoices, setLiveInvoices] = useState(null);
  const [loadError, setLoadError] = useState(null);

  // Load data from Supabase when we have a session
  useEffect(() => {
    if (!session || !window._rfpSupabase || !clientId) return;
    let cancelled = false;

    async function loadData() {
      try {
        const sb = window._rfpSupabase;
        // Find the client_company row for this session user
        const { data: { user } } = await sb.auth.getUser();
        if (!user || cancelled) return;

        // Look up client_company by portal_user_id
        const { data: ccData, error: ccError } = await sb.from("client_companies")
          .select("id, name, railroad_code, company_id")
          .eq("portal_user_id", user.id)
          .single();

        if (ccError || !ccData || cancelled) {
          // Fall back: try by railroad code from the clientId
          if (clientId) {
            const code = clientId.replace('cli-', '').toUpperCase();
            const { data: ccByCode } = await sb.from("client_companies")
              .select("id, name, railroad_code, company_id")
              .eq("railroad_code", code)
              .single();
            if (ccByCode && !cancelled) {
              await loadByClientCompany(sb, ccByCode, clientId, cancelled);
            }
          }
          return;
        }

        if (!cancelled) {
          await loadByClientCompany(sb, ccData, clientId, cancelled);
        }
      } catch (err) {
        if (!cancelled) {
          console.warn("Client portal: Supabase load failed, using static data.", err);
          setLoadError(err.message);
        }
      }
    }

    async function loadByClientCompany(sb, ccData, cid, cancelled) {
      // Load jobs for this client company
      const { data: jobsData, error: jobsError } = await sb.from("jobs")
        .select("*")
        .eq("client_company_id", ccData.id);

      if (!cancelled && !jobsError && jobsData) {
        setLiveJobs(jobsData.map(j => normalizeJob(j, cid)));
      }

      // Load invoices for this client company
      const { data: invData, error: invError } = await sb.from("invoices")
        .select("*")
        .eq("client_company_id", ccData.id);

      if (!cancelled && !invError && invData) {
        setLiveInvoices(invData.map(i => normalizeInvoice(i, cid)));
      }
    }

    loadData();
    return () => { cancelled = true; };
  }, [session, clientId]);

  // Use live data when available, fall back to static prototype data
  const jobs = useMemo(() => {
    if (liveJobs !== null) return liveJobs;
    return ALL_JOBS.filter(j => j.clientId === clientId);
  }, [liveJobs, clientId]);

  const invoices = useMemo(() => {
    if (liveInvoices !== null) return liveInvoices;
    return ALL_INVOICES.filter(i => i.clientId === clientId);
  }, [liveInvoices, clientId]);

  // doLogin now supports async Supabase auth
  const doLogin = useCallback(async (email, pw) => {
    let res;
    if (RFP.loginAsync) {
      res = await RFP.loginAsync(email, pw, 'client');
    } else {
      res = RFP.login(email, pw, 'client');
    }
    if (res.ok) setSession(res.session);
    return res;
  }, []);

  const doLogout = useCallback(async () => {
    RFP.logout();
    setSession(null);
    setLiveJobs(null);
    setLiveInvoices(null);
  }, []);

  const [activeDoc, setActiveDoc] = useState(null);
  const [toasts, setToasts] = useState([]);
  const toast = useCallback((text, kind = 'info', ms = 2600) => {
    const id = 'c' + Math.random().toString(36).slice(2, 7);
    setToasts(t => [...t, { id, text, kind }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), ms);
  }, []);

  const value = useMemo(() => ({
    session, doLogin, doLogout, client, clientId, jobs, invoices,
    loadError, isLive: liveJobs !== null || liveInvoices !== null,
    activeDoc, setActiveDoc, toasts, toast,
  }), [session, doLogin, doLogout, client, clientId, jobs, invoices, loadError, liveJobs, liveInvoices, activeDoc, toasts, toast]);

  return <ClientCtx.Provider value={value}>{children}</ClientCtx.Provider>;
}
const useClient = () => useContext(ClientCtx);

Object.assign(window, { ClientCtx, ClientProvider, useClient, CLIENTS, ALL_JOBS, ALL_INVOICES, C_money, C_num, C_date });
