<template>
  <Teleport to="body">
    <div
      v-if="visible"
      class="fixed inset-0 z-50 flex items-center justify-center"
      @click.self="close"
      @keydown.esc="close"
    >
      <!-- Backdrop -->
      <div class="absolute inset-0 bg-black/50" @click="close" />

      <!-- Dialog -->
      <div class="relative w-full max-w-md bg-[#161b22] border border-[#30363d] rounded-lg shadow-2xl overflow-hidden">
        <!-- Header -->
        <div class="flex items-center justify-between px-4 py-3 border-b border-[#30363d]">
          <h3 class="text-sm font-semibold text-[var(--wraith-text-primary)]">
            {{ isEditing ? "Edit Connection" : "New Connection" }}
          </h3>
          <button
            class="text-[var(--wraith-text-muted)] hover:text-[var(--wraith-text-primary)] transition-colors cursor-pointer"
            @click="close"
          >
            <svg class="w-4 h-4" viewBox="0 0 16 16" fill="currentColor">
              <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 1 1 1.06 1.06L9.06 8l3.22 3.22a.749.749 0 1 1-1.06 1.06L8 9.06l-3.22 3.22a.749.749 0 1 1-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z" />
            </svg>
          </button>
        </div>

        <!-- Body -->
        <div class="px-4 py-4 space-y-3 max-h-[80vh] overflow-y-auto">
          <!-- Name -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Name</label>
            <input
              v-model="form.name"
              type="text"
              placeholder="My Server"
              class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
            />
          </div>

          <!-- Hostname & Port -->
          <div class="flex gap-3">
            <div class="flex-1">
              <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Hostname</label>
              <input
                v-model="form.hostname"
                type="text"
                placeholder="192.168.1.1"
                class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
              />
            </div>
            <div class="w-24">
              <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Port</label>
              <input
                v-model.number="form.port"
                type="number"
                class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
              />
            </div>
          </div>

          <!-- Protocol -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Protocol</label>
            <div class="flex gap-2">
              <button
                class="flex-1 py-2 text-sm rounded border transition-colors cursor-pointer"
                :class="form.protocol === 'ssh'
                  ? 'bg-[#3fb950]/10 border-[#3fb950] text-[#3fb950]'
                  : 'bg-[#0d1117] border-[#30363d] text-[var(--wraith-text-muted)] hover:border-[var(--wraith-text-secondary)]'
                "
                @click="setProtocol('ssh')"
              >
                SSH
              </button>
              <button
                class="flex-1 py-2 text-sm rounded border transition-colors cursor-pointer"
                :class="form.protocol === 'rdp'
                  ? 'bg-[#1f6feb]/10 border-[#1f6feb] text-[#1f6feb]'
                  : 'bg-[#0d1117] border-[#30363d] text-[var(--wraith-text-muted)] hover:border-[var(--wraith-text-secondary)]'
                "
                @click="setProtocol('rdp')"
              >
                RDP
              </button>
            </div>
          </div>

          <!-- Group -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Group</label>
            <select
              v-model="form.groupId"
              class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors cursor-pointer"
            >
              <option :value="null">No Group</option>
              <option v-for="group in connectionStore.groups" :key="group.id" :value="group.id">
                {{ group.name }}
              </option>
            </select>
          </div>

          <!-- Tags -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Tags (comma-separated)</label>
            <input
              v-model="tagsInput"
              type="text"
              placeholder="Prod, Linux, Web"
              class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
            />
          </div>

          <!-- Color -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Color Label</label>
            <div class="flex gap-2">
              <button
                v-for="color in colorOptions"
                :key="color.value"
                class="w-6 h-6 rounded-full border-2 transition-transform cursor-pointer hover:scale-110"
                :class="form.color === color.value ? 'border-white scale-110' : 'border-transparent'"
                :style="{ backgroundColor: color.hex }"
                :title="color.label"
                @click="form.color = color.value"
              />
            </div>
          </div>

          <!-- Notes -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Notes</label>
            <textarea
              v-model="form.notes"
              rows="3"
              placeholder="Optional notes about this connection..."
              class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors resize-none"
            />
          </div>

          <!-- Divider -->
          <div class="border-t border-[#30363d]" />

          <!-- Credentials -->
          <div>
            <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Credential</label>
            <div class="flex gap-2">
              <select
                v-model="form.credentialId"
                class="flex-1 px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors cursor-pointer"
              >
                <option :value="null">None</option>
                <option
                  v-for="cred in credentials"
                  :key="cred.id"
                  :value="cred.id"
                >
                  {{ cred.name }}
                  <template v-if="cred.type === 'ssh_key'"> (SSH Key)</template>
                  <template v-else> (Password{{ cred.username ? ` — ${cred.username}` : '' }})</template>
                </option>
              </select>
              <button
                v-if="form.credentialId"
                type="button"
                class="px-2.5 py-2 text-xs rounded border border-red-500/30 text-red-400 hover:bg-red-500/10 transition-colors cursor-pointer"
                title="Delete selected credential"
                @click="deleteSelectedCredential"
              >
                Delete
              </button>
            </div>
          </div>

          <!-- Add New Credential (collapsible) -->
          <div class="rounded border border-[#30363d] overflow-hidden">
            <!-- Toggle header -->
            <button
              class="w-full flex items-center justify-between px-3 py-2 text-xs text-[var(--wraith-text-secondary)] hover:bg-[#1c2128] transition-colors cursor-pointer"
              @click="showNewCred = !showNewCred"
            >
              <span class="font-medium">Add New Credential</span>
              <svg
                class="w-3.5 h-3.5 transition-transform"
                :class="showNewCred ? 'rotate-180' : ''"
                viewBox="0 0 16 16"
                fill="currentColor"
              >
                <path d="M4.427 7.427l3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z" />
              </svg>
            </button>

            <!-- Collapsed content -->
            <div v-if="showNewCred" class="px-3 pb-3 pt-2 space-y-3 bg-[#0d1117]">
              <!-- Credential type selector -->
              <div class="flex gap-2">
                <button
                  class="flex-1 py-1.5 text-xs rounded border transition-colors cursor-pointer"
                  :class="newCredType === 'password'
                    ? 'bg-[#3fb950]/10 border-[#3fb950] text-[#3fb950]'
                    : 'bg-transparent border-[#30363d] text-[var(--wraith-text-muted)] hover:border-[var(--wraith-text-secondary)]'
                  "
                  @click="newCredType = 'password'"
                >
                  Password
                </button>
                <button
                  class="flex-1 py-1.5 text-xs rounded border transition-colors cursor-pointer"
                  :class="newCredType === 'ssh_key'
                    ? 'bg-[#58a6ff]/10 border-[#58a6ff] text-[#58a6ff]'
                    : 'bg-transparent border-[#30363d] text-[var(--wraith-text-muted)] hover:border-[var(--wraith-text-secondary)]'
                  "
                  @click="newCredType = 'ssh_key'"
                >
                  SSH Key
                </button>
              </div>

              <!-- Password fields -->
              <template v-if="newCredType === 'password'">
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Credential Name</label>
                  <input
                    v-model="newCred.name"
                    type="text"
                    placeholder="e.g. prod-admin"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Username</label>
                  <input
                    v-model="newCred.username"
                    type="text"
                    placeholder="admin"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Password</label>
                  <input
                    v-model="newCred.password"
                    type="password"
                    placeholder="••••••••"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
              </template>

              <!-- SSH Key fields -->
              <template v-if="newCredType === 'ssh_key'">
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Credential Name</label>
                  <input
                    v-model="newCred.name"
                    type="text"
                    placeholder="e.g. my-ssh-key"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Username</label>
                  <input
                    v-model="newCred.username"
                    type="text"
                    placeholder="e.g. vstockwell"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Private Key (PEM)</label>
                  <textarea
                    v-model="newCred.privateKeyPEM"
                    rows="5"
                    placeholder="-----BEGIN OPENSSH PRIVATE KEY-----&#10;...&#10;-----END OPENSSH PRIVATE KEY-----"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors resize-none font-mono"
                    spellcheck="false"
                  />
                </div>
                <div>
                  <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Passphrase <span class="text-[var(--wraith-text-muted)]">(optional)</span></label>
                  <input
                    v-model="newCred.passphrase"
                    type="password"
                    placeholder="Leave blank if key is unencrypted"
                    class="w-full px-3 py-2 text-sm rounded bg-[#161b22] border border-[#30363d] text-[var(--wraith-text-primary)] placeholder-[var(--wraith-text-muted)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors"
                  />
                </div>
              </template>

              <!-- Error message -->
              <p v-if="newCredError" class="text-xs text-[#f85149]">{{ newCredError }}</p>

              <!-- Save credential button -->
              <button
                class="w-full py-1.5 text-xs rounded border transition-colors cursor-pointer"
                :class="isNewCredValid
                  ? 'bg-[#238636] border-[#238636] text-white hover:bg-[#2ea043] hover:border-[#2ea043]'
                  : 'bg-transparent border-[#30363d] text-[var(--wraith-text-muted)] cursor-not-allowed opacity-50'
                "
                :disabled="!isNewCredValid || savingCred"
                @click="saveNewCredential"
              >
                {{ savingCred ? 'Saving...' : 'Save Credential' }}
              </button>
            </div>
          </div>
        </div>

        <!-- Footer -->
        <div class="flex items-center justify-end gap-2 px-4 py-3 border-t border-[#30363d]">
          <button
            class="px-3 py-1.5 text-xs text-[var(--wraith-text-secondary)] hover:text-[var(--wraith-text-primary)] rounded border border-[#30363d] hover:bg-[#30363d] transition-colors cursor-pointer"
            @click="close"
          >
            Cancel
          </button>
          <button
            class="px-3 py-1.5 text-xs text-white bg-[#238636] hover:bg-[#2ea043] rounded transition-colors cursor-pointer"
            :class="{ 'opacity-50 cursor-not-allowed': !isValid }"
            :disabled="!isValid"
            @click="save"
          >
            {{ isEditing ? "Save Changes" : "Create" }}
          </button>
        </div>
      </div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";
import { useConnectionStore, type Connection } from "@/stores/connection.store";
import { Call } from "@wailsio/runtime";

/** Fully qualified Go method name prefix for ConnectionService bindings. */
const CONN = "github.com/vstockwell/wraith/internal/connections.ConnectionService";
/**
 * Credential methods are proxied through WraithApp (registered at startup)
 * because CredentialService is nil until vault unlock and can't be pre-registered.
 */
const APP = "github.com/vstockwell/wraith/internal/app.WraithApp";

interface Credential {
  id: number;
  name: string;
  username: string;
  domain: string;
  type: "password" | "ssh_key";
  sshKeyId: number | null;
}

interface ConnectionForm {
  name: string;
  hostname: string;
  port: number;
  protocol: "ssh" | "rdp";
  groupId: number | null;
  credentialId: number | null;
  color: string;
  notes: string;
}

interface NewCredForm {
  name: string;
  username: string;
  password: string;
  privateKeyPEM: string;
  passphrase: string;
}

const connectionStore = useConnectionStore();

const visible = ref(false);
const isEditing = ref(false);
const editingId = ref<number | null>(null);
const tagsInput = ref("");

const credentials = ref<Credential[]>([]);

// New credential panel state
const showNewCred = ref(false);
const newCredType = ref<"password" | "ssh_key">("password");
const savingCred = ref(false);
const newCredError = ref("");
const newCred = ref<NewCredForm>({
  name: "",
  username: "",
  password: "",
  privateKeyPEM: "",
  passphrase: "",
});

const form = ref<ConnectionForm>({
  name: "",
  hostname: "",
  port: 22,
  protocol: "ssh",
  groupId: null,
  credentialId: null,
  color: "",
  notes: "",
});

const colorOptions = [
  { value: "", label: "None", hex: "#30363d" },
  { value: "red", label: "Red", hex: "#f85149" },
  { value: "orange", label: "Orange", hex: "#d29922" },
  { value: "green", label: "Green", hex: "#3fb950" },
  { value: "blue", label: "Blue", hex: "#58a6ff" },
  { value: "purple", label: "Purple", hex: "#bc8cff" },
  { value: "pink", label: "Pink", hex: "#f778ba" },
];

const isValid = computed(() => {
  return form.value.name.trim() !== "" && form.value.hostname.trim() !== "" && form.value.port > 0;
});

const isNewCredValid = computed(() => {
  if (!newCred.value.name.trim()) return false;
  if (newCredType.value === "password") {
    return newCred.value.password.length > 0;
  }
  // ssh_key: must have PEM content
  return newCred.value.privateKeyPEM.trim().length > 0;
});

function setProtocol(protocol: "ssh" | "rdp"): void {
  form.value.protocol = protocol;
  if (protocol === "ssh" && form.value.port === 3389) {
    form.value.port = 22;
  } else if (protocol === "rdp" && form.value.port === 22) {
    form.value.port = 3389;
  }
}

function resetNewCredForm(): void {
  newCred.value = { name: "", username: "", password: "", privateKeyPEM: "", passphrase: "" };
  newCredError.value = "";
}

async function deleteSelectedCredential(): Promise<void> {
  if (!form.value.credentialId) return;
  const cred = credentials.value.find(c => c.id === form.value.credentialId);
  const name = cred?.name ?? `ID ${form.value.credentialId}`;
  if (!confirm(`Delete credential "${name}"? This cannot be undone.`)) return;
  try {
    await Call.ByName(`${APP}.DeleteCredential`, form.value.credentialId);
    form.value.credentialId = null;
    await loadCredentials();
  } catch (err) {
    alert(`Failed to delete credential: ${err}`);
  }
}

async function loadCredentials(): Promise<void> {
  try {
    const result = await Call.ByName(`${APP}.ListCredentials`) as Credential[];
    credentials.value = result || [];
  } catch (err) {
    credentials.value = [];
  }
}

async function saveNewCredential(): Promise<void> {
  if (!isNewCredValid.value || savingCred.value) return;
  savingCred.value = true;
  newCredError.value = "";

  try {
    let created: Credential | null = null;

    if (newCredType.value === "password") {
      created = await Call.ByName(
        `${APP}.CreatePassword`,
        newCred.value.name.trim(),
        newCred.value.username.trim(),
        newCred.value.password,
        "",  // domain — not collected in this form
      ) as Credential;
    } else {
      // SSH Key: CreateSSHKeyCredential(name, username, privateKeyPEM string, passphrase string)
      created = await Call.ByName(
        `${APP}.CreateSSHKeyCredential`,
        newCred.value.name.trim(),
        newCred.value.username.trim(),
        newCred.value.privateKeyPEM.trim(),
        newCred.value.passphrase,
      ) as Credential;
    }

    // Refresh list and auto-select the new credential
    await loadCredentials();
    if (created) {
      form.value.credentialId = created.id;
    }

    resetNewCredForm();
    showNewCred.value = false;
  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    newCredError.value = msg || "Failed to save credential.";
  } finally {
    savingCred.value = false;
  }
}

function openNew(groupId?: number): void {
  isEditing.value = false;
  editingId.value = null;
  form.value = {
    name: "",
    hostname: "",
    port: 22,
    protocol: "ssh",
    groupId: groupId ?? null,
    credentialId: null,
    color: "",
    notes: "",
  };
  tagsInput.value = "";
  resetNewCredForm();
  showNewCred.value = false;
  void loadCredentials();
  visible.value = true;
}

function openEdit(conn: Connection): void {
  isEditing.value = true;
  editingId.value = conn.id;
  form.value = {
    name: conn.name,
    hostname: conn.hostname,
    port: conn.port,
    protocol: conn.protocol,
    groupId: conn.groupId,
    credentialId: conn.credentialId ?? null,
    color: conn.color ?? "",
    notes: conn.notes ?? "",
  };
  tagsInput.value = conn.tags?.join(", ") ?? "";
  resetNewCredForm();
  showNewCred.value = false;
  void loadCredentials();
  visible.value = true;
}

function close(): void {
  visible.value = false;
}

async function save(): Promise<void> {
  if (!isValid.value) return;

  const tags = tagsInput.value
    .split(",")
    .map((t) => t.trim())
    .filter((t) => t.length > 0);

  try {
    if (isEditing.value && editingId.value !== null) {
      await Call.ByName(`${CONN}.UpdateConnection`, editingId.value, {
        name: form.value.name,
        hostname: form.value.hostname,
        port: form.value.port,
        groupId: form.value.groupId,
        credentialId: form.value.credentialId,
        color: form.value.color,
        tags,
        notes: form.value.notes,
      });
    } else {
      await Call.ByName(`${CONN}.CreateConnection`, {
        name: form.value.name,
        hostname: form.value.hostname,
        port: form.value.port,
        protocol: form.value.protocol,
        groupId: form.value.groupId,
        credentialId: form.value.credentialId,
        color: form.value.color,
        tags,
        notes: form.value.notes,
      });
    }
    // Refresh connections from backend
    await connectionStore.loadAll();
    close();
  } catch (err) {
    console.error("Failed to save connection:", err);
  }
}

defineExpose({ openNew, openEdit, close, visible });
</script>
