<script lang="ts">
  import { browser } from '$app/environment';
  import { goto } from '$app/navigation';
  import { onMount } from 'svelte';
  import {
    isAuthenticated, getRoutingRules, createRoutingRule, updateRoutingRule,
    deleteRoutingRule, toggleRoutingRule, reorderRoutingRules, getNodes,
    type RouteRule, type NodeInfo
  } from '$lib/api';
  import { toast } from 'svelte-sonner';
  import { Plus, Trash2, Save, X, ArrowLeftRight, ArrowUp, ArrowDown } from 'lucide-svelte';

  let rules: RouteRule[] = [];
  let nodes: NodeInfo[] = [];
  let loading = true;

  let editing: string | null = null;
  let editData: Partial<RouteRule> & { pool_ids_str?: string } = {};
  let creating = false;
  let newData: Partial<RouteRule> & { pool_ids_str?: string } = {
    action_type: 'auto',
    priority: 10,
    action_pool_ids: [] as string[],
  };

  // Regex test inputs
  let testCallerId = '';
  let testDest = '';
  let testIngress = '';

  if (browser && !isAuthenticated()) { goto('/login'); }

  onMount(async () => {
    await loadAll();
    await loadNodes();
  });

  async function loadAll() {
    loading = true;
    try { rules = await getRoutingRules(); }
    catch (e: any) { toast.error(e.message); }
    finally { loading = false; }
  }

  async function loadNodes() {
    try { nodes = await getNodes(); }
    catch { /* nodes optional */ }
  }

  // --- Helpers ---

  function matches(str: string, pattern: string): boolean {
    if (!str || !pattern) return false;
    try { return new RegExp(pattern).test(str); } catch { return false; }
  }

  function joinPoolIDs(ids: string[] | undefined): string {
    return (ids || []).join(',');
  }

  function splitPoolIDs(s: string | undefined): string[] {
    if (!s) return [];
    return s.split(',').map(x => x.trim()).filter(x => x);
  }

  // --- CRUD ---

  function startEdit(r: RouteRule) {
    editing = r.id;
    editData = {
      ...r,
      pool_ids_str: joinPoolIDs(r.action_pool_ids),
    };
  }

  function cancelEdit() {
    editing = null;
    creating = false;
    editData = {};
    newData = { action_type: 'auto', priority: 10, action_pool_ids: [] };
    testCallerId = testDest = testIngress = '';
  }

  async function saveEdit() {
    if (!editing) return;
    try {
      const payload = { ...editData };
      (payload as any).action_pool_ids = splitPoolIDs((payload as any).pool_ids_str);
      delete (payload as any).pool_ids_str;

      const updated = await updateRoutingRule(editing, payload);
      const idx = rules.findIndex(r => r.id === editing);
      if (idx >= 0) rules[idx] = updated;
      editing = null;
      toast.success('Правило обновлено');
    } catch (e: any) { toast.error(e.message); }
  }

  async function saveCreate() {
    const payload: any = { ...newData };
    if (!payload.name?.trim()) { toast.error('Название обязательно'); return; }

    if (payload.action_type === 'pool') {
      payload.action_pool_ids = splitPoolIDs(payload.pool_ids_str);
    } else if (payload.action_type === 'node') {
      payload.action_pool_ids = [];
    }
    delete payload.pool_ids_str;

    try {
      const created = await createRoutingRule(payload);
      rules = [...rules, created];
      cancelEdit();
      toast.success('Правило создано');
    } catch (e: any) { toast.error(e.message); }
  }

  async function removeRule(id: string) {
    if (!confirm('Удалить правило?')) return;
    try {
      await deleteRoutingRule(id);
      rules = rules.filter(r => r.id !== id);
      toast.success('Правило удалено');
    } catch (e: any) { toast.error(e.message); }
  }

  async function toggleRule(id: string, enabled: boolean) {
    try {
      const updated = await toggleRoutingRule(id, enabled);
      rules = rules.map(r => r.id === id ? updated : r);
    } catch (e: any) { toast.error(e.message); }
  }

  async function moveRule(idx: number, dir: -1 | 1) {
    const ni = idx + dir;
    if (ni < 0 || ni >= rules.length) return;
    const reordered = [...rules];
    [reordered[idx], reordered[ni]] = [reordered[ni], reordered[idx]];
    try {
      await reorderRoutingRules(reordered.map(r => r.id));
      await loadAll();
    } catch (e: any) { toast.error(e.message); }
  }

  // --- Display ---

  function actionBadge(t: string): string {
    switch (t) {
      case 'node': return 'bg-violet-100 text-violet-700';
      case 'pool': return 'bg-sky-100 text-sky-700';
      default: return 'bg-gray-100 text-gray-700';
    }
  }

  function actionLabel(t: string): string {
    switch (t) { case 'node': return 'Нода'; case 'pool': return 'Пул'; default: return 'Авто'; }
  }

  function matchSummary(r: RouteRule): string {
    const parts: string[] = [];
    if (r.match_caller_id) parts.push('CID');
    if (r.match_destination) parts.push('Dest');
    if (r.match_ingress_trunk) parts.push('Trunk');
    if (r.match_days) parts.push('Days=' + r.match_days);
    if (r.match_time_start || r.match_time_end) parts.push((r.match_time_start || '--') + '-' + (r.match_time_end || '--'));
    return parts.length > 0 ? parts.join(', ') : '—';
  }

  function timeDisplay(r: RouteRule): string {
    if (!r.match_days && !r.match_time_start && !r.match_time_end) return '—';
    const parts: string[] = [];
    if (r.match_days) parts.push('дни ' + r.match_days);
    if (r.match_time_start || r.match_time_end) parts.push((r.match_time_start || '--') + '–' + (r.match_time_end || '--'));
    return parts.join(' ');
  }
</script>

<div class="space-y-6">
  <div class="flex items-center justify-between">
    <h1 class="text-xl font-bold flex items-center gap-2"><ArrowLeftRight class="h-5 w-5" /> Маршрутизация</h1>
    <button on:click={() => (creating = true)} class="flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-md text-sm font-medium hover:opacity-90">
      <Plus class="h-4 w-4" /> Добавить правило
    </button>
  </div>

  {#if creating}
    <div class="border rounded-lg p-4 bg-yellow-50 border-yellow-200 space-y-3">
      <h3 class="text-sm font-semibold">Новое правило маршрутизации</h3>

      <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
        <input class="px-3 py-2 border rounded-md text-sm" placeholder="Название правила *" bind:value={newData.name} />
        <input class="px-3 py-2 border rounded-md text-sm" placeholder="Приоритет (меньше = раньше)" type="number" bind:value={newData.priority} />
      </div>

      <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
        <div>
          <label class="text-xs text-muted-foreground">Caller ID (regex)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm font-mono" placeholder="^7\d{10}$" bind:value={newData.match_caller_id} />
        </div>
        <div>
          <label class="text-xs text-muted-foreground">Destination (regex)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm font-mono" placeholder="^383122.*$" bind:value={newData.match_destination} />
        </div>
      </div>

      <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
        <div>
          <label class="text-xs text-muted-foreground">Ingress Trunk (regex)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm font-mono" placeholder="^trk-.*$" bind:value={newData.match_ingress_trunk} />
        </div>
        <div>
          <label class="text-xs text-muted-foreground">Дни недели ("1-5" = пн-пт)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm" placeholder="1-5" bind:value={newData.match_days} />
        </div>
      </div>

      <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
        <div>
          <label class="text-xs text-muted-foreground">Начало (HH:MM)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm" placeholder="09:00" bind:value={newData.match_time_start} />
        </div>
        <div>
          <label class="text-xs text-muted-foreground">Конец (HH:MM)</label>
          <input class="w-full px-3 py-2 border rounded-md text-sm" placeholder="18:00" bind:value={newData.match_time_end} />
        </div>
      </div>

      <div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
        <div>
          <label class="text-xs text-muted-foreground">Действие</label>
          <select class="w-full px-3 py-2 border rounded-md text-sm bg-background" bind:value={newData.action_type}>
            <option value="auto">Авто (scoring)</option>
            <option value="node">Нода</option>
            <option value="pool">Пул нод</option>
          </select>
        </div>

        {#if newData.action_type === 'node'}
          <div>
            <label class="text-xs text-muted-foreground">Node ID</label>
            <select class="w-full px-3 py-2 border rounded-md text-sm bg-background font-mono" bind:value={newData.action_node_id}>
              <option value="">— выбрать —</option>
              {#each nodes as n}
                <option value={n.node_id}>{n.node_id}</option>
              {/each}
            </select>
          </div>
        {:else if newData.action_type === 'pool'}
          <div class="col-span-2">
            <label class="text-xs text-muted-foreground">Node IDs (через запятую)</label>
            <input class="w-full px-3 py-2 border rounded-md text-sm font-mono" placeholder="asterisk01,asterisk02" bind:value={newData.pool_ids_str} />
            {#if nodes.length > 0}
              <div class="mt-1 flex flex-wrap gap-1">
                {#each nodes as n}
                  <label class="flex items-center gap-1 text-xs px-2 py-1 border rounded cursor-pointer hover:bg-secondary">
                    <input type="checkbox" checked={splitPoolIDs(newData.pool_ids_str).includes(n.node_id)}
                      on:change={(e) => {
                        const current = splitPoolIDs(newData.pool_ids_str);
                        const target = e.target as HTMLInputElement;
                        newData.pool_ids_str = target.checked
                          ? [...current, n.node_id].join(',')
                          : current.filter(id => id !== n.node_id).join(',');
                      }} />
                    {n.node_id}
                  </label>
                {/each}
              </div>
            {/if}
          </div>
        {/if}
      </div>

      <div>
        <label class="text-xs text-muted-foreground">Описание</label>
        <input class="w-full px-3 py-2 border rounded-md text-sm" placeholder="Для чего это правило" bind:value={newData.description} />
      </div>

      <!-- Regex test -->
      <div class="border-t pt-3">
        <p class="text-xs font-medium text-muted-foreground mb-2">Проверка regex</p>
        <div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
          {#each [
            { label: 'Caller ID', val: testCallerId, bind: (v: string) => testCallerId = v, pattern: newData.match_caller_id },
            { label: 'Destination', val: testDest, bind: (v: string) => testDest = v, pattern: newData.match_destination },
            { label: 'Ingress Trunk', val: testIngress, bind: (v: string) => testIngress = v, pattern: newData.match_ingress_trunk },
          ] as item}
            <div>
              <input class="w-full px-3 py-2 border rounded-md text-sm" placeholder={`Тест ${item.label}`} value={item.val} on:input={(e) => item.bind(e.currentTarget.value)} />
              {#if item.val && item.pattern}
                <span class="text-xs {matches(item.val, item.pattern) ? 'text-green-600' : 'text-red-600'}">
                  {matches(item.val, item.pattern) ? '✓ match' : '✗ no match'}
                </span>
              {/if}
            </div>
          {/each}
        </div>
      </div>

      <div class="flex gap-2 pt-2">
        <button on:click={saveCreate} class="flex items-center gap-1 px-3 py-2 bg-primary text-primary-foreground rounded-md text-sm"><Save class="h-3 w-3" /> Создать</button>
        <button on:click={cancelEdit} class="flex items-center gap-1 px-3 py-2 border rounded-md text-sm"><X class="h-3 w-3" /> Отмена</button>
      </div>
    </div>
  {/if}

  {#if loading}
    <p class="text-muted-foreground text-sm">Загрузка...</p>
  {:else if rules.length === 0}
    <p class="text-muted-foreground text-sm py-8 text-center">
      Нет правил маршрутизации. Звонки идут через стандартный скоринг.
    </p>
  {:else}
    <div class="border rounded-lg overflow-hidden">
      <table class="w-full text-sm">
        <thead class="bg-secondary">
          <tr>
            <th class="px-3 py-3 text-left font-medium w-16">#</th>
            <th class="px-3 py-3 text-left font-medium">Название</th>
            <th class="px-3 py-3 text-left font-medium">Условия</th>
            <th class="px-3 py-3 text-left font-medium">Действие</th>
            <th class="px-3 py-3 text-left font-medium">Время</th>
            <th class="px-3 py-3 text-center font-medium w-12">Hits</th>
            <th class="px-3 py-3 text-center font-medium w-14">Вкл</th>
            <th class="px-3 py-3 text-right font-medium w-32">Действия</th>
          </tr>
        </thead>
        <tbody>
          {#each rules as r, idx (r.id)}
            {#if editing === r.id}
              <tr class="border-t bg-yellow-50">
                <td class="px-3 py-2 text-center font-mono text-xs">{r.priority}</td>
                <td class="px-3 py-2"><input class="w-full px-2 py-1 border rounded text-sm" bind:value={editData.name} /></td>
                <td class="px-3 py-2"><div class="space-y-1">
                  <input class="w-full px-2 py-1 border rounded text-xs font-mono" placeholder="CID" bind:value={editData.match_caller_id} />
                  <input class="w-full px-2 py-1 border rounded text-xs font-mono" placeholder="Dest" bind:value={editData.match_destination} />
                  <input class="w-full px-2 py-1 border rounded text-xs font-mono" placeholder="Trunk" bind:value={editData.match_ingress_trunk} />
                </div></td>
                <td class="px-3 py-2">
                  <select class="w-full px-2 py-1 border rounded text-xs mb-1" bind:value={editData.action_type}>
                    <option value="auto">Авто</option>
                    <option value="node">Нода</option>
                    <option value="pool">Пул</option>
                  </select>
                  {#if editData.action_type === 'node'}
                    <input class="w-full px-2 py-1 border rounded text-xs font-mono" placeholder="node_id" bind:value={editData.action_node_id} />
                  {:else if editData.action_type === 'pool'}
                    <input class="w-full px-2 py-1 border rounded text-xs font-mono" placeholder="id1,id2" bind:value={editData.pool_ids_str} />
                  {/if}
                </td>
                <td class="px-3 py-2"><div class="space-y-1">
                  <input class="w-full px-2 py-1 border rounded text-xs" placeholder="дни" bind:value={editData.match_days} />
                  <input class="w-full px-2 py-1 border rounded text-xs" placeholder="с" bind:value={editData.match_time_start} />
                  <input class="w-full px-2 py-1 border rounded text-xs" placeholder="по" bind:value={editData.match_time_end} />
                </div></td>
                <td class="px-3 py-2 text-center text-xs">{r.hits ?? 0}</td>
                <td class="px-3 py-2 text-center"><label class="flex justify-center"><input type="checkbox" checked={editData.enabled} /></label></td>
                <td class="px-3 py-2 text-right">
                  <div class="flex gap-1 justify-end">
                    <button on:click={saveEdit} class="px-2 py-1 bg-primary text-primary-foreground rounded text-xs"><Save class="h-3 w-3 inline" /></button>
                    <button on:click={cancelEdit} class="px-2 py-1 border rounded text-xs"><X class="h-3 w-3 inline" /></button>
                  </div>
                </td>
              </tr>
            {:else}
              <tr class="border-t hover:bg-secondary/50">
                <td class="px-3 py-3 text-center">
                  <div class="flex items-center justify-center gap-0.5">
                    <button on:click={() => moveRule(idx, -1)} disabled={idx === 0} class="text-muted-foreground hover:text-primary disabled:opacity-20"><ArrowUp class="h-3 w-3" /></button>
                    <span class="w-5 font-mono text-xs">{r.priority}</span>
                    <button on:click={() => moveRule(idx, 1)} disabled={idx === rules.length - 1} class="text-muted-foreground hover:text-primary disabled:opacity-20"><ArrowDown class="h-3 w-3" /></button>
                  </div>
                </td>
                <td class="px-3 py-3 font-medium">{r.name}</td>
                <td class="px-3 py-3 font-mono text-xs text-muted-foreground max-w-56 break-all">{matchSummary(r)}</td>
                <td class="px-3 py-3">
                  <span class="px-2 py-1 rounded text-xs font-medium {actionBadge(r.action_type)}">
                    {actionLabel(r.action_type)}
                    {#if r.action_type === 'node' && r.action_node_id}
                      <span class="ml-1 font-mono opacity-70">{r.action_node_id}</span>
                    {:else if r.action_type === 'pool' && r.action_pool_ids?.length}
                      <span class="ml-1 font-mono opacity-70">{r.action_pool_ids.length} нод</span>
                    {/if}
                  </span>
                </td>
                <td class="px-3 py-3 text-xs text-muted-foreground">{timeDisplay(r)}</td>
                <td class="px-3 py-3 text-center font-mono text-xs">{r.hits ?? 0}</td>
                <td class="px-3 py-3 text-center">
                  <button on:click={() => toggleRule(r.id, !r.enabled)} class="text-xs">{r.enabled ? '🟢' : '🔴'}</button>
                </td>
                <td class="px-3 py-3 text-right">
                  <button on:click={() => startEdit(r)} class="px-2 py-1 text-xs text-primary hover:underline mr-1">Изменить</button>
                  <button on:click={() => removeRule(r.id)} class="px-2 py-1 text-xs text-destructive hover:underline"><Trash2 class="h-3 w-3 inline" /></button>
                </td>
              </tr>
            {/if}
          {/each}
        </tbody>
      </table>
    </div>
  {/if}
</div>
