<script>
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
import { compileRuleExpr, createRule, updateRule, fetchRule } from '$lib/api/rule.js';
  import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js';
  import { ArrowLeft, Save, Loader2, AlertCircle, CheckCircle2, RefreshCw, Code } from 'lucide-svelte';

  /** @typedef {'idle' | 'success' | 'error' | 'stale' | 'loading'} CompileStatus */

  /** @type {{ ruleId?: number | null, mode?: 'create' | 'edit' }} */
  let { ruleId = null, mode = 'create' } = $props();

  // Form state
  let ruleCode = $state('');
  let ruleName = $state('');
  let eventCode = $state('ORDER_CREATED');
  let rawExpr = $state('');

  // Compile state
  let compiledExprJson = $state(null);
  let compiledExprObject = $state(null);
  let compileStatus = $state(/** @type {CompileStatus} */ ('idle'));
  let compileError = $state(null);
  let lastCompiledRawExpr = $state(null);

  // UI state
  let isSaving = $state(false);
  let formErrors = $state(/** @type {Record<string, string>} */ ({}));

  // Load existing rule in edit mode
  onMount(async () => {
    if (mode === 'edit' && ruleId) {
      await loadRule(ruleId);
    }
  });

  /**
   * Load rule data for editing
   * @param {number} id
   */
  async function loadRule(id) {
    try {
      const response = await fetchRule(id);
      const rule = response?.data?.data ?? response?.data ?? response;

      if (rule) {
        ruleCode = rule.RuleCode ?? '';
        ruleName = rule.RuleName ?? '';
        eventCode = rule.EventCode ?? 'ORDER_CREATED';
        rawExpr = rule.ConditionExpr ?? '';

        // If already has compiled expression, restore that state
        if (rule.ConditionExprCompiled) {
          compiledExprJson = rule.ConditionExprCompiled;
          try {
            compiledExprObject = JSON.parse(rule.ConditionExprCompiled);
          } catch {
            compiledExprObject = null;
          }
          compileStatus = 'success';
          lastCompiledRawExpr = rawExpr;
        } else {
          compileStatus = 'idle';
          lastCompiledRawExpr = null;
          compiledExprJson = null;
          compiledExprObject = null;
        }
        compileError = null;
      }
    } catch (err) {
      toastError(err?.message || 'Failed to load rule');
      goto('/rules');
    }
  }

  /**
   * Handle raw expression change - mark stale if different from last compiled
   * @param {string} value
   */
  function onRawExprChange(value) {
    rawExpr = value;
    if (lastCompiledRawExpr !== null && lastCompiledRawExpr !== value) {
      compileStatus = 'stale';
    }
  }

  /**
   * Compile the raw DSL expression
   */
  async function onCompileClick() {
    // Validate non-empty raw if DSL is required
    // For now, DSL is optional but if provided must be compiled
    if (!rawExpr.trim()) {
      compileError = 'Expression cannot be empty';
      compileStatus = 'error';
      return;
    }

    compileStatus = 'loading';
    compileError = null;

    try {
      const response = await compileRuleExpr(rawExpr);
      const data = response?.data?.data ?? response?.data ?? response;

      if (data?.conditionExprCompiled) {
        compiledExprJson = data.conditionExprCompiled;
        compiledExprObject = data.compiled ?? null;
        compileStatus = 'success';
        lastCompiledRawExpr = rawExpr;
      } else {
        compileError = 'Invalid compile response';
        compileStatus = 'error';
      }
    } catch (err) {
      compileError = err?.message || 'Compilation failed';
      compileStatus = 'error';
    }
  }

  /**
   * Validate required fields
   * @returns {boolean}
   */
  function validateForm() {
    const errors = {};

    if (!ruleCode.trim()) {
      errors.RuleCode = 'Rule Code is required';
    }
    if (!ruleName.trim()) {
      errors.RuleName = 'Rule Name is required';
    }
    if (!eventCode.trim()) {
      errors.EventCode = 'Event Code is required';
    }

    formErrors = errors;
    return Object.keys(errors).length === 0;
  }

  /**
   * Check if save should be disabled
   * @returns {boolean}
   */
  function isSaveDisabled() {
    if (isSaving || compileStatus === 'loading') return true;

    // If raw is empty, save is allowed (optional DSL)
    if (!rawExpr.trim()) return false;

    // If raw exists, must be compiled and fresh
    if (compileStatus !== 'success') return true;
    if (lastCompiledRawExpr !== rawExpr) return true;

    return false;
  }

  /**
   * Get save disabled message
   * @returns {string | null}
   */
  function getSaveDisabledMessage() {
    if (isSaving) return 'Saving...';
    if (compileStatus === 'loading') return 'Compiling...';
    if (!rawExpr.trim()) return null; // Empty is allowed
    if (compileStatus === 'error') return 'Fix compilation error before saving';
    if (compileStatus === 'stale') return 'Recompile required before saving';
    if (compileStatus !== 'success') return 'Compile required before saving';
    if (lastCompiledRawExpr !== rawExpr) return 'Expression changed - recompile required';
    return null;
  }

  /**
   * Save the rule
   */
  async function onSaveClick() {
    if (!validateForm()) return;
    if (isSaveDisabled()) return;

    isSaving = true;

    try {
      const payload = {
        RuleCode: ruleCode.trim(),
        RuleName: ruleName.trim(),
        EventCode: eventCode,
        ConditionExpr: rawExpr.trim() || null,
        ConditionExprCompiled: rawExpr.trim() ? compiledExprJson : null,
      };

      if (mode === 'create') {
        await createRule(payload);
        toastSuccess('Rule created successfully');
      } else {
        await updateRule(ruleId, payload);
        toastSuccess('Rule updated successfully');
      }

      goto('/rules');
    } catch (err) {
      const message = err?.message || `Failed to ${mode === 'create' ? 'create' : 'update'} rule`;
      toastError(message);
      if (err?.messages && typeof err.messages === 'object') {
        formErrors = { ...formErrors, ...err.messages };
      }
    } finally {
      isSaving = false;
    }
  }

  /**
   * Get compile status badge UI
   * @returns {{ text: string; class: string; icon: any }}
   */
  function getCompileStatusBadge() {
    switch (compileStatus) {
      case 'idle':
        return { text: 'Not compiled', class: 'badge-ghost', icon: null };
      case 'loading':
        return { text: 'Compiling...', class: 'badge-info', icon: Loader2 };
      case 'success':
        return { text: 'Compiled', class: 'badge-success', icon: CheckCircle2 };
      case 'error':
        return { text: 'Compile failed', class: 'badge-error', icon: AlertCircle };
      case 'stale':
        return { text: 'Needs recompile', class: 'badge-warning', icon: RefreshCw };
      default:
        return { text: 'Unknown', class: 'badge-ghost', icon: null };
    }
  }

  function handleCancel() {
    goto('/rules');
  }

  const statusBadge = $derived(getCompileStatusBadge());
  const saveDisabled = $derived(isSaveDisabled());
  const saveMessage = $derived(getSaveDisabledMessage());
</script>

<div class="p-4 max-w-6xl mx-auto">
  <!-- Page Header -->
  <div class="flex items-center gap-4 mb-6">
    <button class="btn btn-ghost btn-circle" onclick={handleCancel} type="button">
      <ArrowLeft class="w-5 h-5" />
    </button>
    <div class="flex-1">
      <h1 class="text-xl font-bold text-gray-800">
        {mode === 'create' ? 'New Rule' : 'Edit Rule'}
      </h1>
      <p class="text-sm text-gray-600">Global rule with DSL compilation</p>
    </div>
  </div>

  <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
    <!-- Left Column: Fields + DSL Editor -->
    <div class="space-y-6">
      <!-- RuleFieldsCard -->
      <div class="card bg-base-100 shadow-sm border border-base-200">
        <div class="card-body compact-y">
          <h2 class="card-title text-sm font-semibold text-gray-800 mb-4">Rule Information</h2>

          <div class="space-y-4">
            <!-- RuleCode -->
            <div>
              <label class="form-control">
                <div class="label">
                  <span class="label-text font-medium">Rule Code <span class="text-error">*</span></span>
                </div>
                <label class="input input-sm input-bordered flex items-center gap-2 w-full focus-within:input-primary">
                  <Code class="w-4 h-4 text-gray-400" />
                  <input
                    type="text"
                    class="grow bg-transparent outline-none"
                    placeholder="e.g. AUTO_STAT_001"
                    bind:value={ruleCode}
                    disabled={isSaving}
                  />
                </label>
                {#if formErrors.RuleCode}
                  <p class="text-xs text-error mt-1">{formErrors.RuleCode}</p>
                {/if}
              </label>
            </div>

            <!-- RuleName -->
            <div>
              <label class="form-control">
                <div class="label">
                  <span class="label-text font-medium">Rule Name <span class="text-error">*</span></span>
                </div>
                <label class="input input-sm input-bordered flex items-center gap-2 w-full focus-within:input-primary">
                  <Code class="w-4 h-4 text-gray-400" />
                  <input
                    type="text"
                    class="grow bg-transparent outline-none"
                    placeholder="e.g. Auto-set STAT results"
                    bind:value={ruleName}
                    disabled={isSaving}
                  />
                </label>
                {#if formErrors.RuleName}
                  <p class="text-xs text-error mt-1">{formErrors.RuleName}</p>
                {/if}
              </label>
            </div>

            <!-- EventCode -->
            <div>
              <label class="form-control">
                <div class="label">
                  <span class="label-text font-medium">Event Code <span class="text-error">*</span></span>
                </div>
                <select class="select select-sm select-bordered w-full" bind:value={eventCode} disabled={isSaving}>
                  <option value="ORDER_CREATED">ORDER_CREATED</option>
                </select>
                {#if formErrors.EventCode}
                  <p class="text-xs text-error mt-1">{formErrors.EventCode}</p>
                {/if}
              </label>
            </div>
          </div>
        </div>
      </div>

      <!-- DslEditorCard -->
      <div class="card bg-base-100 shadow-sm border border-base-200">
        <div class="card-body compact-y">
          <div class="flex items-center justify-between mb-4">
            <h2 class="card-title text-sm font-semibold text-gray-800">Condition Expression (DSL)</h2>
            <div class="flex items-center gap-2">
              <span class="badge badge-sm {statusBadge.class}">
                {#if statusBadge.icon}
                  <statusBadge.icon class="w-3 h-3 mr-1 inline" />
                {/if}
                {statusBadge.text}
              </span>
            </div>
          </div>

          <div class="space-y-4">
            <!-- Expression Textarea -->
            <textarea
              class="textarea textarea-bordered w-full font-mono text-sm"
              rows="6"
              placeholder="Enter DSL expression..."
              value={rawExpr}
              oninput={(e) => onRawExprChange(e.currentTarget.value)}
              disabled={isSaving}
            ></textarea>

            <!-- Compile Button -->
            <div class="flex items-center justify-between">
              <button
                class="btn btn-sm btn-primary"
                onclick={onCompileClick}
                disabled={compileStatus === 'loading' || isSaving || !rawExpr.trim()}
                type="button"
              >
                {#if compileStatus === 'loading'}
                  <Loader2 class="w-4 h-4 mr-2 animate-spin" />
                  Compiling...
                {:else}
                  <RefreshCw class="w-4 h-4 mr-2" />
                  Compile
                {/if}
              </button>

              {#if compileStatus === 'stale'}
                <span class="text-xs text-warning">Expression changed - needs recompile</span>
              {/if}
            </div>

            <!-- Inline Compile Error -->
            {#if compileError}
              <div class="alert alert-error alert-sm">
                <AlertCircle class="w-4 h-4" />
                <span class="text-sm">{compileError}</span>
              </div>
            {/if}

            <!-- DSL Helper Examples -->
            <div class="bg-base-200 rounded-lg p-3">
              <div class="text-xs font-semibold text-gray-700 mb-2 flex items-center gap-2">
                <Code class="w-3.5 h-3.5" />
                DSL Examples
              </div>
              <pre class="text-xs text-gray-600 overflow-auto">if(sex('F') ? set_result(0.7) : set_result(1))
order.isStat ? set_result('URGENT') : set_result('NORMAL')
patient.age > 65 ? set_result(true) : skip()</pre>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Right Column: Compiled Preview + Actions -->
    <div class="space-y-6">
      <!-- CompiledPreviewCard -->
      <div class="card bg-base-100 shadow-sm border border-base-200">
        <div class="card-body compact-y">
          <h2 class="card-title text-sm font-semibold text-gray-800 mb-4">Compiled Output</h2>

          {#if compiledExprObject && compileStatus === 'success'}
            <div class="bg-base-200 rounded-lg p-3">
              <pre class="text-xs font-mono overflow-auto whitespace-pre-wrap break-all">{JSON.stringify(
                  compiledExprObject,
                  null,
                  2
                )}</pre>
            </div>
          {:else}
            <div class="text-center py-8 text-gray-500">
              <Code class="w-12 h-12 mx-auto mb-3 text-gray-300" />
              <p class="text-sm">Compile expression to see output</p>
            </div>
          {/if}
        </div>
      </div>

      <!-- FormActions -->
      <div class="card bg-base-100 shadow-sm border border-base-200">
        <div class="card-body compact-y">
          <h2 class="card-title text-sm font-semibold text-gray-800 mb-4">Actions</h2>

          <div class="space-y-3">
            {#if saveMessage}
              <div class="alert alert-warning alert-sm">
                <AlertCircle class="w-4 h-4" />
                <span class="text-sm">{saveMessage}</span>
              </div>
            {/if}

            <div class="flex gap-3">
              <button
                class="btn btn-ghost flex-1"
                onclick={handleCancel}
                disabled={isSaving || compileStatus === 'loading'}
                type="button"
              >
                Cancel
              </button>

              <button
                class="btn btn-primary flex-1"
                onclick={onSaveClick}
                disabled={saveDisabled}
                type="button"
              >
                {#if isSaving}
                  <Loader2 class="w-4 h-4 mr-2 animate-spin" />
                  Saving...
                {:else}
                  <Save class="w-4 h-4 mr-2" />
                  {mode === 'create' ? 'Create Rule' : 'Update Rule'}
                {/if}
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
