import { type Component, createSignal, createResource, For, Show } from "solid-js";
import { rulesApi } from "../api/client";
import type { InterceptionRule } from "../types";
import { Button } from "./ui/Button";
import { Card } from "./ui/Card";
import { Input } from "./ui/Input";
import { Select } from "./ui/Select";
import { Textarea } from "./ui/Textarea";

const RulesList: Component = () => {
  const [rules, { refetch }] = createResource(rulesApi.list);
  const [showEditor, setShowEditor] = createSignal(false);
  const [editingId, setEditingId] = createSignal<number | null>(null);
  const [editingMethod, setEditingMethod] = createSignal("");
  const [editingAction, setEditingAction] = createSignal<"passthrough" | "modify" | "replace">("passthrough");
  const [editingResponse, setEditingResponse] = createSignal("");

  const toggleRule = async (rule: InterceptionRule) => {
    try {
      await rulesApi.update(rule.id, {
        is_enabled: !rule.is_enabled,
      });
      refetch();
    } catch (err) {
      console.error("Failed to toggle rule:", err);
      alert(`Error: ${err}`);
    }
  };

  const deleteRule = async (id: number) => {
    if (!confirm("Are you sure you want to delete this rule?")) return;

    try {
      if (id === editingId()) {
        setShowEditor(false);
      }
      await rulesApi.delete(id);
      refetch();
    } catch (err) {
      console.error("Failed to delete rule:", err);
      alert(`Error: ${err}`);
    }
  };

  const createNewRule = async () => {
    if (!editingMethod()) {
      alert("Please enter a method name");
      return;
    }

    try {
      await rulesApi.create({
        method_name: editingMethod(),
        action: editingAction(),
        custom_response: editingAction() === "replace" ? editingResponse() : undefined,
      });
      setShowEditor(false);
      setEditingMethod("");
      setEditingResponse("");
      refetch();
    } catch (err) {
      console.error("Failed to create rule:", err);
      alert(`Error: ${err}`);
    }
  };

  const startEdit = (rule: InterceptionRule) => {
    setEditingId(rule.id);
    setEditingMethod(rule.method_name);
    setEditingAction(rule.action);
    setEditingResponse(rule.custom_response || "");
    setShowEditor(true);
  };

  const cancelEdit = () => {
    setEditingId(null);
    setEditingMethod("");
    setEditingAction("passthrough");
    setEditingResponse("");
    setShowEditor(false);
  };

  const saveEdit = async () => {
    const id = editingId();
    if (id === null) {
      await createNewRule();
      return;
    }

    if (!editingMethod()) {
      alert("Please enter a method name");
      return;
    }

    try {
      await rulesApi.update(id, {
        method_name: editingMethod(),
        action: editingAction(),
        custom_response: editingAction() === "replace" ? editingResponse() : undefined,
      });
      cancelEdit();
      refetch();
    } catch (err) {
      console.error("Failed to update rule:", err);
      alert(`Error: ${err}`);
    }
  };

  return (
    <div class="space-y-4">
      <div class="flex justify-between items-center">
        <h2 class="text-2xl font-semibold">Interception Rules</h2>
        <Button
          onClick={() => {
            if (showEditor()) {
              cancelEdit();
            } else {
              setShowEditor(true);
            }
          }}
        >
          {showEditor() ? "Cancel" : "+ New Rule"}
        </Button>
      </div>

      <Show when={showEditor()}>
        <Card class="p-6 mb-4">
          <h3 class="text-lg font-semibold mb-4">{editingId() !== null ? "Edit Rule" : "Create New Rule"}</h3>
          <div class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">Method Name</label>
              <Input
                type="text"
                value={editingMethod()}
                onInput={(e) => setEditingMethod(e.currentTarget.value)}
                placeholder="com.linspirer.method.name"
              />
            </div>

            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">Action</label>
              <Select
                value={editingAction()}
                onChange={(e) => setEditingAction(e.currentTarget.value as any)}
              >
                <option value="passthrough">Passthrough (Forward to server)</option>
                <option value="replace">Replace (Custom response)</option>
              </Select>
            </div>

            <Show when={editingAction() === "replace"}>
              <div>
                <label class="block text-sm font-medium text-gray-700 mb-1">Custom Response (JSON)</label>
                <Textarea
                  value={editingResponse()}
                  onInput={(e) => setEditingResponse(e.currentTarget.value)}
                  rows={10}
                  placeholder='{"code": 0, "type": "object", "data": {...}}'
                />
              </div>
            </Show>

            <Button onClick={saveEdit}>{editingId() !== null ? "Update Rule" : "Create Rule"}</Button>
          </div>
        </Card>
      </Show>

      <Card>
        <div class="overflow-x-auto">
          <table class="min-w-full divide-y divide-gray-200">
            <thead class="bg-gray-50">
              <tr>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Method Name</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Action</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Status</th>
                <th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase">Actions</th>
              </tr>
            </thead>
            <tbody class="bg-white divide-y divide-gray-200">
              <Show
                when={!rules.loading}
                fallback={
                  <tr>
                    <td colspan="4" class="p-8 text-center text-gray-500">
                      Loading...
                    </td>
                  </tr>
                }
              >
                <For
                  each={rules()}
                  fallback={
                    <tr>
                      <td colspan="4" class="text-center py-8 text-gray-500">
                        No rules configured yet. Click "+ New Rule" to create one.
                      </td>
                    </tr>
                  }
                >
                  {(rule) => (
                    <tr>
                      <td class="px-6 py-4 text-sm font-medium text-gray-900">{rule.method_name}</td>
                      <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                        <span
                          class={`px-2 py-1 rounded-full text-xs ${
                            rule.action === "replace"
                              ? "bg-purple-100 text-purple-800"
                              : rule.action === "modify"
                                ? "bg-blue-100 text-blue-800"
                                : "bg-gray-100 text-gray-800"
                          }`}
                        >
                          {rule.action}
                        </span>
                      </td>
                      <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                        <button
                          onClick={() => toggleRule(rule)}
                          class={`px-3 py-1 rounded-md text-sm font-medium ${
                            rule.is_enabled ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-800"
                          }`}
                        >
                          {rule.is_enabled ? "✓ Enabled" : "✗ Disabled"}
                        </button>
                      </td>
                      <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
                        <Button variant="ghost" onClick={() => startEdit(rule)} class="mr-4">
                          Edit
                        </Button>
                        <Button variant="link" onClick={() => deleteRule(rule.id)}>
                          Delete
                        </Button>
                      </td>
                    </tr>
                  )}
                </For>
              </Show>
            </tbody>
          </table>
        </div>
      </Card>
    </div>
  );
};

export default RulesList;
