<script setup lang="ts">
import { computed, onMounted, reactive, watch } from "vue";
import { useRouter } from "vue-router";
import { authState, clearAuthSession } from "./auth";
import { ensureConnection, stopConnection } from "./realtime";
import { privateRoutes, publicRoutes } from "./router";
import { loadUserSettings, saveNavigationMode, userSettings } from "./user-settings";
import logoUrl from "../../images/icons/companytool-logo.png";
import AdminRegistrationsPage from "./views/AdminRegistrationsPage.vue";
import OrganizationSetupPage from "./views/OrganizationSetupPage.vue";
import UsersPage from "./views/UsersPage.vue";
import CustomersPage from "./views/CustomersPage.vue";
import SuppliersPage from "./views/SuppliersPage.vue";
import ItemsPage from "./views/ItemsPage.vue";
import ActivitiesPage from "./views/ActivitiesPage.vue";
import CashDiscountTermsPage from "./views/CashDiscountTermsPage.vue";
import NumberRangesPage from "./views/NumberRangesPage.vue";
import QuotesPage from "./views/QuotesPage.vue";
import OutgoingInvoicesPage from "./views/OutgoingInvoicesPage.vue";
import IncomingInvoicesPage from "./views/IncomingInvoicesPage.vue";
import PriceImportsPage from "./views/PriceImportsPage.vue";
import ApiConnectorsPage from "./views/ApiConnectorsPage.vue";
import PriceRulesPage from "./views/PriceRulesPage.vue";
import CommunicationsPage from "./views/CommunicationsPage.vue";
import DocumentsPage from "./views/DocumentsPage.vue";

const router = useRouter();
const routes = computed(() => (authState.session ? privateRoutes : publicRoutes));
const activeNavGroup = reactive<{ label: string | null }>({ label: null });
const privateRouteGroups = computed(() => {
  const groups: Array<{ label: string; routes: typeof privateRoutes }> = [];
  for (const route of privateRoutes) {
    const groupLabel = route.group;
    let group = groups.find((item) => item.label === groupLabel);
    if (!group) {
      group = { label: groupLabel, routes: [] };
      groups.push(group);
    }
    group.routes.push(route);
  }
  return groups;
});
const windowComponents = {
  "/admin/organization-registrations": AdminRegistrationsPage,
  "/setup/organization": OrganizationSetupPage,
  "/settings/users": UsersPage,
  "/settings/number-ranges": NumberRangesPage,
  "/master-data/customers": CustomersPage,
  "/master-data/suppliers": SuppliersPage,
  "/master-data/items": ItemsPage,
  "/settings/cash-discount-terms": CashDiscountTermsPage,
  "/quotes": QuotesPage,
  "/outgoing-invoices": OutgoingInvoicesPage,
  "/incoming-invoices": IncomingInvoicesPage,
  "/imports/price-lists": PriceImportsPage,
  "/settings/api-connectors": ApiConnectorsPage,
  "/settings/price-rules": PriceRulesPage,
  "/communications": CommunicationsPage,
  "/documents": DocumentsPage,
  "/activities": ActivitiesPage
};
type WindowPath = keyof typeof windowComponents;
type AppWindow = {
  path: WindowPath;
  title: string;
  z: number;
  x: number;
  y: number;
  width: number;
  height: number;
  minimized: boolean;
};
const openWindows = reactive<AppWindow[]>([]);
let nextZ = 10;
let activeDrag:
  | {
      path: WindowPath;
      mode: "move" | "resize";
      pointerId: number;
      startX: number;
      startY: number;
      windowX: number;
      windowY: number;
      windowWidth: number;
      windowHeight: number;
    }
  | null = null;

onMounted(() => {
  ensureConnection();
  if (authState.session) {
    loadUserSettings();
  }
  restoreWindows();
});

watch(
  () => authState.session?.userId,
  () => {
    if (authState.session) {
      loadUserSettings();
    }
    restoreWindows();
  }
);

function logout() {
  openWindows.splice(0);
  clearAuthSession();
  stopConnection();
  router.push("/login");
}

function openAppWindow(route: { path: string; label: string }) {
  activeNavGroup.label = null;
  if (route.path === "/") {
    router.push("/");
    return;
  }
  if (!(route.path in windowComponents)) {
    router.push(route.path);
    return;
  }
  const path = route.path as keyof typeof windowComponents;
  const existing = openWindows.find((window) => window.path === path);
  if (existing) {
    existing.minimized = false;
    focusWindow(existing);
    persistWindows();
    return;
  }
  openWindows.push(defaultWindow(path, route.label, openWindows.length));
  persistWindows();
}

function toggleGroup(label: string) {
  activeNavGroup.label = activeNavGroup.label === label ? null : label;
}

function closeAppWindow(path: WindowPath) {
  const index = openWindows.findIndex((window) => window.path === path);
  if (index >= 0) {
    openWindows.splice(index, 1);
    persistWindows();
  }
}

function minimizeAppWindow(path: WindowPath) {
  const item = openWindows.find((window) => window.path === path);
  if (!item) return;
  item.minimized = true;
  persistWindows();
}

function restoreAppWindow(item: AppWindow) {
  item.minimized = false;
  focusWindow(item);
}

function focusWindow(item: AppWindow) {
  if (item.minimized) return;
  item.z = ++nextZ;
  persistWindows();
}

function startMove(event: PointerEvent, item: AppWindow) {
  if ((event.target as HTMLElement).closest("button")) return;
  activeDrag = {
    path: item.path,
    mode: "move",
    pointerId: event.pointerId,
    startX: event.clientX,
    startY: event.clientY,
    windowX: item.x,
    windowY: item.y,
    windowWidth: item.width,
    windowHeight: item.height
  };
  focusWindow(item);
  (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
}

function startResize(event: PointerEvent, item: AppWindow) {
  activeDrag = {
    path: item.path,
    mode: "resize",
    pointerId: event.pointerId,
    startX: event.clientX,
    startY: event.clientY,
    windowX: item.x,
    windowY: item.y,
    windowWidth: item.width,
    windowHeight: item.height
  };
  focusWindow(item);
  (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
}

function updatePointer(event: PointerEvent) {
  if (!activeDrag || activeDrag.pointerId !== event.pointerId) return;
  const item = openWindows.find((window) => window.path === activeDrag?.path);
  if (!item) return;
  const deltaX = event.clientX - activeDrag.startX;
  const deltaY = event.clientY - activeDrag.startY;
  if (activeDrag.mode === "move") {
    item.x = clamp(activeDrag.windowX + deltaX, 252, window.innerWidth - 220);
    item.y = clamp(activeDrag.windowY + deltaY, 8, window.innerHeight - 80);
  } else {
    item.width = clamp(activeDrag.windowWidth + deltaX, 560, window.innerWidth - item.x - 16);
    item.height = clamp(activeDrag.windowHeight + deltaY, 360, window.innerHeight - item.y - 16);
  }
}

function endPointer(event: PointerEvent) {
  if (!activeDrag || activeDrag.pointerId !== event.pointerId) return;
  activeDrag = null;
  persistWindows();
}

function defaultWindow(path: WindowPath, title: string, index: number): AppWindow {
  return {
    path,
    title,
    z: ++nextZ,
    x: 280 + index * 28,
    y: 42 + index * 24,
    width: 900,
    height: 680,
    minimized: false
  };
}

function windowStorageKey() {
  return `companytool.windows.${authState.session?.userId ?? "anonymous"}`;
}

function persistWindows() {
  if (!authState.session) return;
  window.localStorage.setItem(
    windowStorageKey(),
    JSON.stringify(
      openWindows.map(({ path, title, z, x, y, width, height, minimized }) => ({
        path,
        title,
        z,
        x,
        y,
        width,
        height,
        minimized
      }))
    )
  );
}

function restoreWindows() {
  openWindows.splice(0);
  if (!authState.session) return;
  try {
    const raw = window.localStorage.getItem(windowStorageKey());
    if (!raw) return;
    const saved = JSON.parse(raw) as AppWindow[];
    for (const item of saved) {
      if (item.path in windowComponents) {
        openWindows.push({
          ...item,
          z: ++nextZ,
          x: clamp(item.x, 252, window.innerWidth - 220),
          y: clamp(item.y, 8, window.innerHeight - 80),
          width: clamp(item.width, 560, window.innerWidth - item.x - 16),
          height: clamp(item.height, 360, window.innerHeight - item.y - 64),
          minimized: item.minimized === true
        });
      }
    }
  } catch {
    openWindows.splice(0);
  }
}

function clamp(value: number, min: number, max: number) {
  return Math.max(min, Math.min(value, Math.max(min, max)));
}
</script>

<template>
  <div class="app-shell">
    <aside class="sidebar">
      <div class="brand">
        <img class="brand-mark" :src="logoUrl" alt="Company Tool Logo" />
        <div>
          <strong>Company Tool</strong>
          <span>Organisationen</span>
        </div>
      </div>
      <nav class="nav" :class="`nav-${userSettings.navigationMode}`">
        <template v-if="!authState.session">
          <RouterLink
            v-for="route in routes"
            :key="route.path"
            :to="route.path"
            class="nav-link"
          >
            {{ route.label }}
          </RouterLink>
        </template>
        <template v-if="authState.session && userSettings.navigationMode === 'groups'">
          <template v-for="group in privateRouteGroups" :key="group.label">
            <div class="nav-dropdown">
              <button type="button" class="nav-group-toggle" @click="toggleGroup(group.label)">
                <span>{{ group.label }}</span>
                <span>{{ activeNavGroup.label === group.label ? "^" : "v" }}</span>
              </button>
              <div v-if="activeNavGroup.label === group.label" class="nav-dropdown-menu">
                <button
                  v-for="route in group.routes"
                  :key="route.path"
                  type="button"
                  class="nav-link nav-button"
                  @click="openAppWindow(route)"
                >
                  {{ route.label }}
                </button>
              </div>
            </div>
          </template>
        </template>
        <template v-else-if="authState.session">
          <template v-for="group in privateRouteGroups" :key="group.label">
            <div class="nav-group-title">{{ group.label }}</div>
            <button
              v-for="route in group.routes"
              :key="route.path"
              type="button"
              class="nav-link nav-button"
              :class="{ active: route.path === '/' }"
              @click="openAppWindow(route)"
            >
              {{ route.label }}
            </button>
          </template>
        </template>
      </nav>
      <div v-if="authState.session" class="session-box">
        <label class="field settings-field">
          <span>Menü</span>
          <select
            :value="userSettings.navigationMode"
            @change="saveNavigationMode(($event.target as HTMLSelectElement).value as 'scroll' | 'groups')"
          >
            <option value="scroll">Scrollbar</option>
            <option value="groups">Gruppen einklappen</option>
          </select>
        </label>
        <small v-if="userSettings.status">{{ userSettings.status }}</small>
        <span>{{ authState.session.email }}</span>
        <button type="button" class="secondary" @click="logout">Abmelden</button>
      </div>
    </aside>
    <main class="main">
      <RouterView />
      <section
        v-for="item in openWindows"
        v-show="!item.minimized"
        :key="item.path"
        class="app-window"
        :style="{ zIndex: item.z, left: `${item.x}px`, top: `${item.y}px`, width: `${item.width}px`, height: `${item.height}px` }"
        @mousedown="focusWindow(item)"
        @pointermove="updatePointer"
        @pointerup="endPointer"
        @pointercancel="endPointer"
      >
        <header class="app-window-title" @pointerdown="startMove($event, item)">
          <strong>{{ item.title }}</strong>
          <span class="app-window-actions">
            <button type="button" class="secondary icon-button" @click="minimizeAppWindow(item.path)">_</button>
            <button type="button" class="secondary icon-button" @click="closeAppWindow(item.path)">×</button>
          </span>
        </header>
        <div class="app-window-body">
          <component :is="windowComponents[item.path]" />
        </div>
        <span class="app-window-resize" @pointerdown="startResize($event, item)" />
      </section>
      <footer v-if="openWindows.length" class="taskbar">
        <button
          v-for="item in openWindows"
          :key="item.path"
          type="button"
          class="taskbar-button"
          :class="{ minimized: item.minimized }"
          @click="restoreAppWindow(item)"
        >
          {{ item.title }}
        </button>
      </footer>
    </main>
  </div>
</template>
