<script setup lang="ts">
import { ref, computed, onMounted, watch } from "vue";
import { useSystemsStore } from "@/stores/systems";
import { useToastStore } from "@/stores/toast";
import { getProjectIssues } from "@/api/systems";
import type { System, TaskLike } from "@/api/systems";
import { Pencil, Trash2, Archive, ArchiveRestore } from "lucide-vue-next";

const props = defineProps<{ projectId: number }>();

const store = useSystemsStore();
const toast = useToastStore();

const error = ref<string | null>(null);
const showArchived = ref(false);
const issues = ref<TaskLike[]>([]);

// Create state
const showCreate = ref(false);
const newName = ref("");
const newDescription = ref("");
const creating = ref(false);

// Edit state
const editingId = ref<number | null>(null);
const editName = ref("");
const editDescription = ref("");
const savingEdit = ref(false);

// Delete confirmation
const deletingSystem = ref<System | null>(null);

const systems = computed<System[]>(() => store.systemsByProject[props.projectId] ?? []);
const activeSystems = computed(() => systems.value.filter((s) => s.status === "active"));
const archivedSystems = computed(() => systems.value.filter((s) => s.status === "archived"));
const visibleSystems = computed(() =>
  showArchived.value ? systems.value : activeSystems.value,
);

async function load() {
  error.value = null;
  try {
    await store.fetchSystems(props.projectId);
  } catch {
    error.value = "Failed to load systems.";
  }
  try {
    issues.value = await getProjectIssues(props.projectId);
  } catch {
    issues.value = [];
  }
}

onMounted(load);
watch(() => props.projectId, load);

function openCreate() {
  showCreate.value = true;
  newName.value = "";
  newDescription.value = "";
}

function cancelCreate() {
  showCreate.value = false;
  newName.value = "";
  newDescription.value = "";
}

async function submitCreate() {
  const name = newName.value.trim();
  if (!name || creating.value) return;
  creating.value = true;
  try {
    await store.createSystem(props.projectId, {
      name,
      description: newDescription.value.trim() || undefined,
    });
    cancelCreate();
    toast.show("System created");
  } catch {
    toast.show("Failed to create system", "error");
  } finally {
    creating.value = false;
  }
}

function startEdit(system: System) {
  editingId.value = system.id;
  editName.value = system.name;
  editDescription.value = system.description;
}

function cancelEdit() {
  editingId.value = null;
}

async function submitEdit(system: System) {
  const name = editName.value.trim();
  if (!name || savingEdit.value) return;
  savingEdit.value = true;
  try {
    await store.updateSystem(props.projectId, system.id, {
      name,
      description: editDescription.value.trim(),
    });
    editingId.value = null;
    toast.show("System updated");
  } catch {
    toast.show("Failed to update system", "error");
  } finally {
    savingEdit.value = false;
  }
}

async function archive(system: System) {
  try {
    await store.archiveSystem(props.projectId, system.id);
    toast.show("System archived");
  } catch {
    toast.show("Failed to archive system", "error");
  }
}

async function unarchive(system: System) {
  try {
    await store.unarchiveSystem(props.projectId, system.id);
    toast.show("System restored");
  } catch {
    toast.show("Failed to restore system", "error");
  }
}

async function confirmDelete() {
  const system = deletingSystem.value;
  if (!system) return;
  deletingSystem.value = null;
  try {
    await store.deleteSystem(props.projectId, system.id);
    toast.show("System deleted");
  } catch {
    toast.show("Failed to delete system", "error");
  }
}
</script>

<template>
  <div class="systems-section">
    <!-- Open issues -->
    <div v-if="issues.length" class="open-issues">
      <div class="open-issues-label">⚠ Open issues ({{ issues.length }})</div>
      <ul class="issue-list">
        <li v-for="issue in issues" :key="issue.id" class="issue-item">
          <router-link :to="`/tasks/${issue.id}`" class="issue-link">
            <span class="issue-mark" :class="`imk-${issue.status}`">{{ issue.status === 'in_progress' ? '▸' : '○' }}</span>
            <span class="issue-name">{{ issue.title }}</span>
            <span v-if="issue.systems && issue.systems.length" class="issue-systems">
              <span v-for="s in issue.systems" :key="s.id" class="issue-sys-chip">{{ s.name }}</span>
            </span>
          </router-link>
        </li>
      </ul>
    </div>

    <!-- Toolbar -->
    <div class="systems-toolbar">
      <button v-if="!showCreate" class="btn-ghost btn-inline btn-add-system" @click="openCreate">
        + System
      </button>
      <label v-if="archivedSystems.length" class="archived-toggle">
        <input v-model="showArchived" type="checkbox" class="archived-checkbox" />
        Show archived ({{ archivedSystems.length }})
      </label>
    </div>

    <!-- Create form -->
    <form v-if="showCreate" class="system-form" @submit.prevent="submitCreate">
      <input
        v-model="newName"
        class="fs-input system-input"
        placeholder="System name"
        aria-label="System name"
        autofocus
        @keydown.escape="cancelCreate"
      />
      <textarea
        v-model="newDescription"
        class="fs-input system-textarea"
        rows="2"
        placeholder="What is this subsystem responsible for? (optional)"
        aria-label="System description"
      ></textarea>
      <div class="system-form-actions">
        <button type="submit" class="btn-primary btn-compact" :disabled="!newName.trim() || creating">
          {{ creating ? "Creating…" : "Create" }}
        </button>
        <button type="button" class="btn-ghost btn-compact" @click="cancelCreate">Cancel</button>
      </div>
    </form>

    <!-- Loading -->
    <div v-if="store.loading && !systems.length" class="systems-skeleton" aria-label="Loading systems">
      <div class="skel-row"></div>
      <div class="skel-row skel-row--short"></div>
      <div class="skel-row"></div>
    </div>

    <!-- Error -->
    <p v-else-if="error" class="error-msg">{{ error }}</p>

    <!-- Empty -->
    <div v-else-if="!visibleSystems.length" class="systems-empty">
      <p class="empty-title">No systems yet</p>
      <p class="empty-sub">Define a reusable subsystem or area to organize issues against.</p>
      <button v-if="!showCreate" class="btn-primary btn-compact" @click="openCreate">+ Create a system</button>
    </div>

    <!-- List -->
    <ul v-else class="systems-list">
      <li
        v-for="system in visibleSystems"
        :key="system.id"
        class="system-card"
        :class="{ 'system-card--archived': system.status === 'archived' }"
      >
        <!-- Inline edit -->
        <template v-if="editingId === system.id">
          <form class="system-form system-form--inline" @submit.prevent="submitEdit(system)">
            <input
              v-model="editName"
              class="fs-input system-input"
              placeholder="System name"
              aria-label="System name"
              autofocus
              @keydown.escape="cancelEdit"
            />
            <textarea
              v-model="editDescription"
              class="fs-input system-textarea"
              rows="2"
              placeholder="Description (optional)"
              aria-label="System description"
            ></textarea>
            <div class="system-form-actions">
              <button type="submit" class="btn-primary btn-compact" :disabled="!editName.trim() || savingEdit">
                {{ savingEdit ? "Saving…" : "Save" }}
              </button>
              <button type="button" class="btn-ghost btn-compact" @click="cancelEdit">Cancel</button>
            </div>
          </form>
        </template>

        <!-- Display -->
        <template v-else>
          <span
            class="system-swatch"
            :style="{ background: system.color || 'var(--fs-text-tertiary)' }"
            aria-hidden="true"
          ></span>
          <div class="system-body">
            <div class="system-name-row">
              <span class="system-name">{{ system.name }}</span>
              <span
                class="issue-badge"
                :title="`${system.open_issue_count} open issue(s)`"
              >{{ system.open_issue_count }} open</span>
              <span v-if="system.status === 'archived'" class="archived-badge">Archived</span>
            </div>
            <p v-if="system.description" class="system-description">{{ system.description }}</p>
          </div>
          <div class="system-actions">
            <button class="action-btn" title="Edit" aria-label="Edit system" @click="startEdit(system)">
              <Pencil :size="16" />
            </button>
            <button
              v-if="system.status === 'active'"
              class="action-btn"
              title="Archive"
              aria-label="Archive system"
              @click="archive(system)"
            >
              <Archive :size="16" />
            </button>
            <button
              v-else
              class="action-btn"
              title="Restore"
              aria-label="Restore system"
              @click="unarchive(system)"
            >
              <ArchiveRestore :size="16" />
            </button>
            <button
              class="action-btn action-delete"
              title="Delete"
              aria-label="Delete system"
              @click="deletingSystem = system"
            >
              <Trash2 :size="16" />
            </button>
          </div>
        </template>
      </li>
    </ul>

    <!-- Delete confirmation -->
    <teleport to="body">
      <div v-if="deletingSystem" class="modal-overlay" @click.self="deletingSystem = null">
        <div class="modal-card">
          <h3 class="modal-title">Delete System</h3>
          <p class="modal-message">
            Delete <strong>{{ deletingSystem.name }}</strong>? This cannot be undone.
          </p>
          <div class="modal-actions">
            <button class="modal-btn" @click="deletingSystem = null">Cancel</button>
            <button class="modal-btn modal-btn-danger" @click="confirmDelete">Delete</button>
          </div>
        </div>
      </div>
    </teleport>
  </div>
</template>

<style scoped>
.systems-section { display: flex; flex-direction: column; gap: 0.75rem; }

/* ── Open issues ──────────────────────────────────────────────── */
.open-issues { display: flex; flex-direction: column; gap: 0.35rem; }
.open-issues-label { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--fs-text-tertiary); }
.issue-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.issue-link { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; border-radius: var(--fs-radius-sm); text-decoration: none; color: var(--fs-text-primary); font-size: 0.85rem; }
.issue-link:hover { background: var(--fs-surface-raised); }
.issue-mark { color: var(--fs-text-tertiary); flex-shrink: 0; }
.issue-mark.imk-in_progress { color: var(--fs-accent); }
.issue-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.issue-systems { display: flex; gap: 0.25rem; flex-shrink: 0; flex-wrap: wrap; }
.issue-sys-chip { font-size: 0.66rem; color: var(--fs-text-secondary); background: var(--fs-surface-raised); border-radius: 999px; padding: 0.05rem 0.4rem; }

/* ── Toolbar ──────────────────────────────────────────────────── */
.systems-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.btn-add-system {
  background: none;
  border: 1px dashed var(--fs-border-color);
  color: var(--fs-text-secondary);
  padding: 0.28rem 0.65rem;
  border-radius: var(--fs-radius-sm);
  cursor: pointer;
  font-size: 0.78rem;
  font-family: inherit;
}
.btn-add-system:hover { border-color: var(--fs-accent); color: var(--fs-accent); }
.btn-add-system:focus-visible { outline: none; border-color: var(--fs-accent); color: var(--fs-accent); }

.archived-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--fs-text-tertiary);
  cursor: pointer;
  user-select: none;
}
.archived-checkbox { accent-color: var(--fs-accent); cursor: pointer; }

/* ── Create / edit form ───────────────────────────────────────── */
.system-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem;
  background: var(--fs-surface-raised);
  border: 1px solid var(--fs-border-color);
  border-radius: var(--fs-radius-lg);
}
.system-form--inline { padding: 0; background: none; border: none; flex: 1; }
/* The input itself is the .fs-input canon (components.css); only the
   layout remainder lives here. */
.system-input, .system-textarea { box-sizing: border-box; width: 100%; }
.system-textarea { resize: vertical; }

.system-form-actions { display: flex; gap: 0.4rem; }

/* RESTORED (#2444). Both lost their base rule to a CSS sweep; only the
   `--archived` modifier and the `:hover .system-actions` reveal survived.
   The card WAS a flex row and every child still says so — `.system-swatch`
   and `.system-actions` are `flex-shrink: 0`, `.system-body` is `flex: 1`,
   and `.system-form--inline` is `flex: 1`. `align-items: flex-start` is why
   the swatch carries `margin-top: 0.3rem`: it is nudged onto the first line
   of text rather than centred against the whole card.

   The list had no rule at all, so it rendered with browser bullets and
   indent — invisible to the dangling-style check, which can only see a class
   that is PARTLY styled. A class with no rules anywhere looks exactly like a
   semantic-only hook.

   Surface values match `.system-form` above, which is the same card shape in
   this file and the reason they can be recovered rather than guessed. */
.systems-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.system-card {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 0.75rem;
  background: var(--fs-surface-raised);
  border: 1px solid var(--fs-border-color);
  border-radius: var(--fs-radius-lg);
}

.system-card--archived { opacity: 0.6; }

.system-swatch {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 0.3rem;
}
.system-body { flex: 1; min-width: 0; }
.system-name-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.system-name { font-weight: 500; color: var(--fs-text-primary); word-break: break-word; }
.issue-badge {
  font-size: 0.7rem;
  font-weight: 500;
  background: color-mix(in srgb, var(--fs-accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--fs-accent) 30%, transparent);
  color: var(--fs-accent);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  flex-shrink: 0;
}
.archived-badge {
  font-size: 0.65rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fs-text-tertiary);
  background: color-mix(in srgb, var(--fs-text-tertiary) 12%, transparent);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}
.system-description {
  margin: 0.25rem 0 0;
  font-size: 0.82rem;
  color: var(--fs-text-secondary);
  line-height: 1.4;
  word-break: break-word;
}

.system-actions { display: flex; gap: 0.15rem; flex-shrink: 0; opacity: 0; transition: opacity 0.15s; }
.system-card:hover .system-actions,
.system-card:focus-within .system-actions { opacity: 1; }
.action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--fs-text-tertiary);
  width: 26px;
  height: 26px;
  border-radius: var(--fs-radius-sm);
  transition: background 0.12s, color 0.12s;
}
.action-btn:hover { background: var(--fs-surface-raised); color: var(--fs-text-primary); }
.action-btn:focus-visible { outline: 2px solid var(--fs-accent); outline-offset: 1px; opacity: 1; }
.action-delete:hover { color: var(--fs-error); }

/* ── Empty ────────────────────────────────────────────────────── */
.systems-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 2rem 1rem;
  text-align: center;
  border: 1px dashed var(--fs-border-color);
  border-radius: var(--fs-radius-lg);
}
.empty-title { margin: 0; font-weight: 500; color: var(--fs-text-primary); }
.empty-sub { margin: 0 0 0.5rem; font-size: 0.82rem; color: var(--fs-text-tertiary); max-width: 32ch; }

.error-msg { color: var(--fs-error); font-size: 0.9rem; }

/* ── Skeleton ─────────────────────────────────────────────────── */
@keyframes skel-shine { to { background-position: 200% center; } }
.systems-skeleton { display: flex; flex-direction: column; gap: 0.4rem; }
.skel-row {
  height: 3rem;
  border-radius: var(--fs-radius-lg);
  background: linear-gradient(
    90deg,
    var(--fs-surface-raised) 25%,
    color-mix(in srgb, var(--fs-text-tertiary) 16%, var(--fs-surface-raised)) 50%,
    var(--fs-surface-raised) 75%
  );
  background-size: 200% 100%;
  animation: skel-shine 1.5s ease infinite;
}
.skel-row--short { width: 65%; }

</style>
