<script>
  import { Search, AlertTriangle } from "@lucide/svelte";
  import Select from "./comps/Select.svelte";
  import { INPUT_TYPES } from "@src/lib/vars";

  let { onSearch = async () => {}, demo = false, initialTarget = "", initialType = "" } = $props();

  const DETECTORS = {
    email:    (_raw, v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
    phone:    (_raw, v) => /^\+\d{1,4} \d{4,}$/.test(v),
    ip:       (_raw, v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')),
    domain:   (raw, v)  => /^https?:\/\//.test(raw) || /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v),
    name:     (_raw, v) => /^[a-zA-ZÀ-ÿ'-]+(?: [a-zA-ZÀ-ÿ'-]+){1,2}$/.test(v),
  };

  const VALIDATORS = {
    email:    { test: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),         msg: "Invalid email address" },
    username: { test: (v) => /^[a-zA-Z0-9._-]+$/.test(v),                   msg: "Username may only contain a-z, 0-9, . - _" },
    phone:    { test: (v) => /^\+\d{1,4} \d{4,}$/.test(v),                 msg: "Format: +COUNTRYCODE NUMBER (e.g. +1 2025550147)" },
    ip:       { test: (v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')), msg: "Invalid IP address" },
    domain:   { test: (v) => /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v), msg: "Invalid domain name" },
  };

  let target = $state(initialTarget);
  let inputType = $state(initialType || "email");
  let profile = $state("default");
  let profiles = $state([]);
  let loading = $state(false);
  let error = $state("");
  let validationError = $state("");
  // null = auto-switch free; "TYPE" = auto-switched from TYPE (show revert); "__locked__" = user overrode, no auto-switch
  let prevType = $state(null);

  let showRevert = $derived(prevType !== null && prevType !== "__locked__");
  let profileOptions = $derived(profiles.map((p) => p.name));

  let strippedTarget = $derived.by(() => {
    let v = target.trim();
    v = v.replace(/^https?:\/\//, "");
    if (v.startsWith("@")) v = v.slice(1);
    return v;
  });

  let detectedType = $derived.by(() => {
    const raw = target.trim();
    const v = strippedTarget;
    if (!v && !raw) return null;
    if (raw.startsWith("@")) return "username";
    for (const [type, fn] of Object.entries(DETECTORS)) {
      if (fn(raw, v)) return type;
    }
    return null;
  });

  async function loadProfiles() {
    try {
      const res = await fetch("/api/config/profiles");
      if (res.ok) profiles = await res.json();
    } catch (_) {}
  }

  loadProfiles();

  function sanitize(s) {
    return s.replace(/[<>"'`&]/g, "").trim();
  }

  function validate(val, type) {
    const v = VALIDATORS[type];
    if (!v) return "";
    return v.test(val) ? "" : v.msg;
  }

  function onTargetInput() {
    if (!strippedTarget) prevType = null; // reset when field is cleared

    if (validationError) validationError = validate(strippedTarget, inputType);

    if (prevType === null && detectedType && detectedType !== inputType) {
      prevType = inputType;
      inputType = detectedType;
    }
  }

  function revert() {
    inputType = prevType;
    prevType = "__locked__";
    validationError = "";
  }

  function onSelectType(v) {
    inputType = v;
    prevType = "__locked__";
    validationError = "";
  }

  async function submit() {
    if (demo) return;
    const clean = sanitize(strippedTarget);
    if (!clean) return;
    validationError = validate(clean, inputType);
    if (validationError) return;
    error = "";
    loading = true;
    try {
      await onSearch(clean, inputType, profile);
      target = "";
      prevType = null;
    } catch (e) {
      error = e.message;
    } finally {
      loading = false;
    }
  }
</script>

<div class="flex flex-col gap-2">
  {#if error}
    <div class="alert alert-error text-sm py-2 gap-2"><AlertTriangle size={15} class="shrink-0" />{error}</div>
  {/if}

  {#if showRevert}
    <div class="flex items-center gap-2 px-1 text-xs text-base-content/50">
      <span>Switched to <span class="text-base-content/70 font-medium">{inputType}</span></span>
      <button
        class="badge badge-ghost badge-sm hover:badge-primary transition-colors cursor-pointer"
        onclick={revert}
      >
        ← {prevType}
      </button>
    </div>
  {/if}

  <!-- Mobile layout -->
  <div class="flex flex-col gap-2 sm:hidden">
    <div class="flex items-center rounded-xl border border-base-content/15 bg-base-300
                focus-within:border-primary/40 transition-colors">
      <input
        class="flex-1 bg-transparent px-4 py-3 outline-none text-sm
               placeholder:text-base-content/30 min-w-0"
        placeholder={demo ? "Search disabled in demo mode" : "Enter target..."}
        bind:value={target}
        oninput={onTargetInput}
        onkeydown={(e) => e.key === "Enter" && submit()}
        disabled={demo}
      />
    </div>
    <div class="flex items-center gap-2">
      <div class="flex items-center gap-1">
        <span class="text-xs text-base-content/25 pl-1">type</span>
        <Select
          options={INPUT_TYPES}
          selected={inputType}
          size="xs"
          onselect={onSelectType}
        />
      </div>
      <div class="flex items-center gap-1">
        <span class="text-xs text-base-content/25">profile</span>
        <Select
          options={profileOptions}
          selected={profile}
          size="xs"
          onselect={(v) => { profile = v; }}
        />
      </div>
    </div>
    <button
      class="btn btn-primary btn-sm w-full gap-1"
      onclick={submit}
      disabled={demo || loading || !target.trim()}
    >
      {#if loading}
        <span class="loading loading-spinner loading-xs"></span>
      {:else}
        <Search size={14} />
      {/if}
      Search
    </button>
  </div>

  <!-- Desktop layout -->
  <div
    class="hidden sm:flex items-center rounded-xl border border-base-content/15 bg-base-300
           focus-within:border-primary/40 transition-colors"
  >
    <div class="border-r border-base-content/10 flex items-center gap-1 pl-3">
      <span class="text-xs text-base-content/25 shrink-0">type</span>
      <Select
        options={INPUT_TYPES}
        selected={inputType}
        onselect={onSelectType}
      />
    </div>

    <input
      class="flex-1 bg-transparent px-4 py-2.5 outline-none text-sm
             placeholder:text-base-content/30 min-w-0"
      placeholder={demo ? "Search disabled in demo mode" : "Enter target..."}
      bind:value={target}
      oninput={onTargetInput}
      onkeydown={(e) => e.key === "Enter" && submit()}
      disabled={demo}
    />

    <div class="border-l border-base-content/10 flex items-center gap-1 pr-1 pl-3">
      <span class="text-xs text-base-content/25 shrink-0">profile</span>
      <Select
        options={profileOptions}
        selected={profile}
        onselect={(v) => { profile = v; }}
      />
    </div>

    <button
      class="btn btn-primary btn-sm m-1 rounded-lg gap-1 shrink-0"
      onclick={submit}
      disabled={demo || loading || !target.trim()}
    >
      {#if loading}
        <span class="loading loading-spinner loading-xs"></span>
      {:else}
        <Search size={14} />
      {/if}
      Search
    </button>
  </div>

  {#if validationError}
    <p class="text-xs text-error pl-1">{validationError}</p>
  {/if}
</div>
