import { useState } from 'react';
import { useBindings, useRoutePreview, useRouteDecisions } from '@insignia/iios-community-web';
import type { RouteDecision } from '@insignia/iios-kernel-client';

export const SERVICE = 'http://localhost:3200';

const STATE_COLORS: Record<string, string> = {
  ALLOW: '#16a34a',
  DENY: '#dc2626',
  REVIEW: '#d97706',
  SUPPRESS: '#6b7280',
  SIMULATED: '#2563eb',
};

/** Inject a signed dev webhook and poll the raw-event log until it normalizes into an interaction. */
async function ingestTestMessage(token: string, text: string): Promise<string> {
  const inject = await fetch(`${SERVICE}/v1/dev/webhook/WEBHOOK`, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ text }),
  });
  if (!inject.ok) throw new Error(`inject ${inject.status}`);
  const { rawEventId } = (await inject.json()) as { rawEventId: string };
  for (let i = 0; i < 40; i++) {
    const r = await fetch(`${SERVICE}/v1/adapters/inbound`, { headers: { authorization: `Bearer ${token}` } });
    const rows = (await r.json()) as Array<{ id: string; interactionId?: string | null }>;
    const hit = rows.find((x) => x.id === rawEventId);
    if (hit?.interactionId) return hit.interactionId;
    await new Promise((res) => setTimeout(res, 150));
  }
  throw new Error('interaction never normalized');
}

const cell: React.CSSProperties = { padding: '6px 10px', borderBottom: '1px solid #eee', verticalAlign: 'top' };
const box: React.CSSProperties = { border: '1px solid #e5e7eb', borderRadius: 8, padding: 16, marginBottom: 16 };

export function App({ token }: { token: string }) {
  const { bindings, createBinding } = useBindings();
  const preview = useRoutePreview();
  const { decisions, approve, deny } = useRouteDecisions({ pollMs: 2000 });

  const [origin, setOrigin] = useState('WEBHOOK');
  const [dest, setDest] = useState('PORTAL');
  const [destRef, setDestRef] = useState('parents-group');
  const [restriction, setRestriction] = useState('');
  const [mode, setMode] = useState('MANUAL');
  const [text, setText] = useState('There is a party at 9 PM tonight!');
  const [simRows, setSimRows] = useState<RouteDecision[]>([]);
  const [busy, setBusy] = useState('');

  const onCreate = async () => {
    await createBinding({
      originChannelType: origin,
      destinationChannelType: dest,
      destinationRef: destRef || undefined,
      restrictionProfile: restriction || undefined,
      mode,
      requiresReview: true,
      enabled: true,
    } as Parameters<typeof createBinding>[0]);
  };

  const onSimulate = async () => {
    setBusy('ingesting…');
    try {
      const interactionId = await ingestTestMessage(token, text);
      setBusy('simulating…');
      setSimRows(await preview(interactionId, origin));
    } catch (e) {
      setBusy(`error: ${(e as Error).message}`);
      return;
    }
    setBusy('');
  };

  return (
    <div style={{ padding: 24, fontFamily: 'sans-serif', maxWidth: 900, margin: '0 auto' }}>
      <h2>IIOS P6 — Route Admin</h2>
      <p style={{ color: '#666' }}>Preview-first. Simulation never sends. Restricted destinations are deny-by-default.</p>

      <div style={box}>
        <h3>1 · Create binding</h3>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>
          <label>origin <input value={origin} onChange={(e) => setOrigin(e.target.value)} style={{ width: 90 }} /></label>
          <span>→</span>
          <label>dest <input value={dest} onChange={(e) => setDest(e.target.value)} style={{ width: 90 }} /></label>
          <label>destRef <input value={destRef} onChange={(e) => setDestRef(e.target.value)} style={{ width: 130 }} /></label>
          <label>
            restriction{' '}
            <select value={restriction} onChange={(e) => setRestriction(e.target.value)}>
              <option value="">(none)</option>
              <option value="CHILD">CHILD</option>
              <option value="ADULT">ADULT</option>
            </select>
          </label>
          <label>
            mode{' '}
            <select value={mode} onChange={(e) => setMode(e.target.value)}>
              <option>MANUAL</option>
              <option>AUTOMATIC</option>
              <option>HYBRID</option>
              <option>SIMULATION_ONLY</option>
            </select>
          </label>
          <button onClick={() => void onCreate()}>+ Add</button>
        </div>
        <table style={{ borderCollapse: 'collapse', width: '100%', marginTop: 12 }}>
          <thead>
            <tr style={{ textAlign: 'left', color: '#666' }}>
              <th style={cell}>origin</th><th style={cell}>destination</th><th style={cell}>restriction</th><th style={cell}>mode</th><th style={cell}>enabled</th>
            </tr>
          </thead>
          <tbody>
            {bindings.map((b) => (
              <tr key={b.id}>
                <td style={cell}>{b.originChannelType}{b.originRef ? `:${b.originRef}` : ''}</td>
                <td style={cell}>{b.destinationChannelType}{b.destinationRef ? `:${b.destinationRef}` : ''}</td>
                <td style={cell}>{b.restrictionProfile ?? '—'}</td>
                <td style={cell}>{b.mode}</td>
                <td style={cell}>{b.enabled ? '✓' : '—'}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div style={box}>
        <h3>2 · Simulate a message (no send)</h3>
        <div style={{ display: 'flex', gap: 8 }}>
          <input value={text} onChange={(e) => setText(e.target.value)} style={{ flex: 1 }} />
          <button onClick={() => void onSimulate()}>Simulate on {origin}</button>
        </div>
        {busy && <p style={{ color: '#666' }}>{busy}</p>}
        {simRows.length > 0 && (
          <table style={{ borderCollapse: 'collapse', width: '100%', marginTop: 12 }}>
            <thead>
              <tr style={{ textAlign: 'left', color: '#666' }}>
                <th style={cell}>destination</th><th style={cell}>decision</th><th style={cell}>reason codes</th><th style={cell}>preview</th>
              </tr>
            </thead>
            <tbody>{simRows.map((d) => <DecisionRow key={d.id} d={d} />)}</tbody>
          </table>
        )}
      </div>

      <div style={box}>
        <h3>3 · Pending decisions (approve / deny)</h3>
        {decisions.length === 0 && <p style={{ color: '#666' }}>No decisions yet — simulate above.</p>}
        <table style={{ borderCollapse: 'collapse', width: '100%' }}>
          <tbody>
            {decisions.map((d) => (
              <tr key={d.id}>
                <DecisionCells d={d} />
                <td style={cell}>
                  {d.decisionState === 'REVIEW' ? (
                    <>
                      <button onClick={() => void approve(d.id)} style={{ marginRight: 6 }}>Approve</button>
                      <button onClick={() => void deny(d.id)}>Deny</button>
                    </>
                  ) : d.executed ? '↪ forwarded (sandbox)' : '—'}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function payloadOf(d: RouteDecision): { text?: string; destinationRef?: string | null } {
  return (d.previewPayload ?? {}) as { text?: string; destinationRef?: string | null };
}

function DecisionRow({ d }: { d: RouteDecision }) {
  const p = payloadOf(d);
  return (
    <tr>
      <td style={cell}>{d.routeBinding ? `${d.routeBinding.destinationChannelType}${d.routeBinding.destinationRef ? `:${d.routeBinding.destinationRef}` : ''}` : (p.destinationRef ?? '—')}</td>
      <td style={{ ...cell, color: STATE_COLORS[d.decisionState] ?? '#000', fontWeight: 600 }}>{d.decisionState}</td>
      <td style={cell}>{d.reasonCodes.join(', ') || '—'}</td>
      <td style={{ ...cell, color: '#555' }}>{p.text ?? '—'}</td>
    </tr>
  );
}

function DecisionCells({ d }: { d: RouteDecision }) {
  const p = payloadOf(d);
  return (
    <>
      <td style={cell}>{d.routeBinding ? `${d.routeBinding.destinationChannelType}${d.routeBinding.destinationRef ? `:${d.routeBinding.destinationRef}` : ''}` : '—'}</td>
      <td style={{ ...cell, color: STATE_COLORS[d.decisionState] ?? '#000', fontWeight: 600 }}>{d.decisionState}</td>
      <td style={cell}>{d.reasonCodes.join(', ') || '—'}</td>
      <td style={{ ...cell, color: '#555' }}>{p.text ?? '—'}</td>
    </>
  );
}
