<template>
  <section class="page">
    <AppLoadingState v-if="isLoading" text="Loading device details" />

    <AppErrorState
      v-else-if="error"
      title="Device loading failed"
      :error="error"
      :retry="init"
    />

    <div v-else-if="device">
      <GnPageHeader :title="device.name || device.alias || `Device #${device.id}`" kicker="Device">
        <template #actions>
          <PageActionsDropdown :items="deviceActions" />
        </template>
      </GnPageHeader>

      <div class="device-meta">
        <GnBadge :variant="device.connection_status === 'active' ? 'success' : 'danger'"
        >{{ device.connection_status === 'active' ? 'Online' : 'Offline' }}</GnBadge>
        <code>{{ device.alias }}</code>
        <AreaBadgeLink :area="area" :areaId="device.area_id" />
      </div>

      <div class="script-info-panel">
        <div class="info-row">
          <span class="info-label text-muted">System status:</span>
          <span class="info-value">
            <GnBadge :variant="systemStatusVariant(device.status)">{{ device.status }}</GnBadge>
          </span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">Type:</span>
          <span class="info-value">{{ device.device_type }}</span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">State:</span>
          <span class="info-value">
            <DeviceChannelsState
              :device-type="device.device_type"
              :response="devicesStore.currentDeviceStatus?.raw"
              :loading="isLoadingStatus"
              :error="statusError?.message"
              :connection-status="device.connection_status"
            />
          </span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">IP:</span>
          <span class="info-value">{{ device.device_ip }}</span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">MAC:</span>
          <span class="info-value">{{ device.device_mac }}</span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">Hard ID:</span>
          <span class="info-value">{{ device.device_hard_id }}</span>
        </div>
        <div class="info-row">
          <span class="info-label text-muted">Firmware:</span>
          <span class="info-value">{{ device.firmware_version }}</span>
        </div>
        <div v-if="device.last_contact" class="info-row">
          <span class="info-label text-muted">Last contact:</span>
          <span class="info-value" :title="formatDateTime(device.last_contact)">{{ formatRelative(device.last_contact) }}</span>
        </div>
        <div v-if="device.create_at" class="info-row">
          <span class="info-label text-muted">Created:</span>
          <span class="info-value">{{ formatDateTime(device.create_at) }}</span>
        </div>
      </div>

      <AreaAssignSection
        :item="device"
        emptyMessage="This device is not assigned to any area."
        @assign="openAssign"
      >
        <template #action>
          <GnButton
            v-if="perm.has('devices.edit')"
            variant="primary"
            icon="ph-map-pin"
            @click="openAssign"
          >
            {{ device?.area_id ? 'Change area' : 'Assign to area' }}
          </GnButton>
        </template>
      </AreaAssignSection>

      <div v-if="hasCompatibleFirmwares && perm.has('firmware.upload')" class="devices-panel">
        <div class="block-title">Firmware Update</div>
        <GnAlert variant="info">
          New firmware available:
          <GnBadge v-for="fw in compatibleFirmwares" :key="fw.id" variant="success">{{ fw.version }}</GnBadge>
        </GnAlert>
        <GnButton variant="primary" icon="ph-cloud-arrow-down" @click="openFirmwareUpdate">
          Update Firmware
        </GnButton>
      </div>

      <div v-if="device.description" class="devices-panel">
        <div class="block-title">Description</div>
        <p>{{ device.description }}</p>
      </div>
    </div>

    <AppEmptyState
      v-else
      title="Device not found"
      message="The requested device does not exist."
    />

    <GnModal :open="showEditModal" title="Edit device" @update:open="showEditModal = $event">
      <div class="form-group">
        <GnInput v-model="editForm.name" label="Name" />
      </div>
      <div class="form-group">
        <GnInput v-model="editForm.description" label="Description" />
      </div>
      <div class="form-group">
        <GnInput v-model="editForm.alias" label="Alias" />
      </div>
      <div v-if="editError" class="form-group">
        <GnAlert variant="danger">{{ editError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showEditModal = false">Cancel</GnButton>
        <GnButton variant="primary" icon="ph-check" :loading="editLoading" @click="submitEdit">
          Save
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showAssignModal"
      title="Assign to area"
      @update:open="showAssignModal = $event"
    >
      <GnSelect
        v-model="selectedAreaId"
        label="Area"
        :options="areaOptions"
        icon="ph-map-trifold"
      />
      <div v-if="assignError" class="form-group">
        <GnAlert variant="danger">{{ assignError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showAssignModal = false">Cancel</GnButton>
        <GnButton
          variant="primary"
          icon="ph-check"
          :loading="assignLoading"
          @click="handleAssignSubmit"
        >
          Assign
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showUnassignDialog"
      title="Unassign from area"
      @update:open="showUnassignDialog = $event"
    >
      <p>{{ unassignDialogMessage }}</p>
      <div v-if="unassignError" class="form-group">
        <GnAlert variant="danger">{{ unassignError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showUnassignDialog = false">Cancel</GnButton>
        <GnButton variant="warning" icon="ph-x-circle" :loading="unassignLoading" @click="submitUnassign">
          Unassign
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showRemoveDialog"
      title="Remove device"
      @update:open="showRemoveDialog = $event"
    >
      <p>{{ removeDialogMessage }}</p>
      <div v-if="removeError" class="form-group">
        <GnAlert variant="danger">{{ removeError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showRemoveDialog = false">Cancel</GnButton>
        <GnButton variant="danger" icon="ph-trash" :loading="removeLoading" @click="submitRemove">
          Remove
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showResetupDialog"
      title="Repeat device setup"
      @update:open="showResetupDialog = $event"
    >
      <p>{{ resetupDialogMessage }}</p>
      <div v-if="resetupError" class="form-group">
        <GnAlert variant="danger">{{ resetupError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showResetupDialog = false">Cancel</GnButton>
        <GnButton variant="primary" icon="ph-gear" :loading="resetupLoading" @click="submitResetup">
          ReSetup
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showResetDialog"
      title="Reset device"
      @update:open="showResetDialog = $event"
    >
      <p>{{ resetDialogMessage }}</p>
      <div v-if="resetError" class="form-group">
        <GnAlert variant="danger">{{ resetError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showResetDialog = false">Cancel</GnButton>
        <GnButton variant="danger" icon="ph-x" :loading="resetLoading" @click="submitReset">
          Reset
        </GnButton>
      </template>
    </GnModal>

    <GnModal
      :open="showFirmwareUpdateModal"
      title="Update Firmware"
      @update:open="showFirmwareUpdateModal = $event"
    >
      <p>Select firmware to install on <strong>{{ device?.name || device?.alias }}</strong>:</p>
      <div class="firmware-options">
        <div
          v-for="fw in compatibleFirmwares"
          :key="fw.id"
          class="firmware-option"
          :class="{ active: selectedFirmwareId === fw.id }"
          @click="selectedFirmwareId = fw.id"
        >
          <div class="fw-version">{{ fw.version }}</div>
          <div v-if="fw.description" class="fw-desc">{{ fw.description }}</div>
        </div>
      </div>
      <div v-if="firmwareUpdateError" class="form-group">
        <GnAlert variant="danger">{{ firmwareUpdateError }}</GnAlert>
      </div>
      <template #footer>
        <GnButton variant="secondary" @click="showFirmwareUpdateModal = false">Cancel</GnButton>
        <GnButton
          variant="primary"
          icon="ph-check"
          :loading="firmwaresStore.isUpdating"
          :disabled="!selectedFirmwareId"
          @click="submitFirmwareUpdate"
        >
          Update
        </GnButton>
      </template>
    </GnModal>
  </section>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useDevicesStore } from "../../../stores/devices";
import { useAreasStore } from "../../../stores/areas";
import { useFirmwaresStore } from "../../../stores/firmwares";
import { usePermission } from "../../../composables/usePermission.js";
import { useAreaAssign } from "../../../composables/useAreaAssign";
import { formatRelative, formatDateTime } from "../../../utils/date.js";
import {
  GnPageHeader,
  GnButton,
  GnBadge,
  GnModal,
  GnInput,
  GnAlert,
  GnSelect,
  useToast,
} from "gnexus-ui-kit/vue";
import AppEmptyState from "../../../components/feedback/AppEmptyState.vue";
import AppErrorState from "../../../components/feedback/AppErrorState.vue";
import AppLoadingState from "../../../components/feedback/AppLoadingState.vue";
import AreaBadgeLink from "../../../components/area/AreaBadgeLink.vue";
import AreaAssignSection from "../../../components/area/AreaAssignSection.vue";
import PageActionsDropdown from "../../../components/layout/PageActionsDropdown.vue";
import DeviceChannelsState from "../components/DeviceChannelsState.vue";

const route = useRoute();
const router = useRouter();
const devicesStore = useDevicesStore();
const areasStore = useAreasStore();
const firmwaresStore = useFirmwaresStore();
const toast = useToast();
const perm = usePermission();

const {
  areaOptions,
  showAssignModal,
  selectedAreaId,
  assignLoading,
  assignError,
  openAssign: openAssignModal,
  submitAssignCore,
} = useAreaAssign();

const deviceId = computed(() => route.params.id);

const device = computed(() => devicesStore.currentDevice);
const isLoading = computed(() => devicesStore.isLoadingDetail);
const error = computed(() => devicesStore.errorDetail);

const isLoadingStatus = ref(false);
const statusError = ref(null);

const area = computed(() => {
  const areaId = device.value?.area_id;
  if (!areaId) return null;
  return areasStore.areasById[String(areaId)] || null;
});

const showEditModal = ref(false);
const editLoading = ref(false);
const editError = ref("");
const editForm = reactive({ name: "", description: "", alias: "" });

const showRemoveDialog = ref(false);
const removeDialogMessage = ref("");
const removeLoading = ref(false);
const removeError = ref("");

const showUnassignDialog = ref(false);
const unassignDialogMessage = ref("");
const unassignLoading = ref(false);
const unassignError = ref("");

const showResetupDialog = ref(false);
const resetupDialogMessage = ref("");
const resetupLoading = ref(false);
const resetupError = ref("");

const showResetDialog = ref(false);
const resetDialogMessage = ref("");
const resetLoading = ref(false);
const resetError = ref("");

const showFirmwareUpdateModal = ref(false);
const selectedFirmwareId = ref(null);
const firmwareUpdateError = ref("");

const hasCompatibleFirmwares = computed(() => {
  return (firmwaresStore.compatibility?.compatible?.length || 0) > 0;
});

const compatibleFirmwares = computed(() => {
  return firmwaresStore.compatibility?.compatible || [];
});


const deviceActions = computed(() => {
  const actions = [];

  if (perm.has('devices.edit')) {
    actions.push({ label: "Edit", icon: "ph-pencil", onSelect: openEdit });

    if (device.value?.area_id) {
      actions.push(
        { label: "Change area", icon: "ph-map-pin", onSelect: openAssign },
        { label: "Unassign from area", icon: "ph-x-circle", onSelect: openUnassign }
      );
    } else {
      actions.push({ label: "Assign to area", icon: "ph-map-pin", onSelect: openAssign });
    }
  }

  if (perm.has('devices.setup')) {
    actions.push({ label: "ReSetup", icon: "ph-gear", onSelect: openResetup });
  }

  if (perm.has('devices.control')) {
    actions.push({
      label: "Reboot",
      icon: "ph-arrow-clockwise",
      disabled: devicesStore.isRebooting(device.value?.id),
      onSelect: reboot,
    });
  }

  if (perm.has('devices.edit')) {
    actions.push({ label: "Reset", icon: "ph-x", danger: true, onSelect: openReset });
  }

  if (perm.has('devices.delete')) {
    actions.push({ label: "Remove", icon: "ph-trash", danger: true, onSelect: remove });
  }

  return actions;
});

function openEdit() {
  if (!device.value) return;
  editForm.name = device.value.name || "";
  editForm.description = device.value.description || "";
  editForm.alias = device.value.alias || "";
  editError.value = "";
  showEditModal.value = true;
}

async function submitEdit() {
  editLoading.value = true;
  editError.value = "";
  const id = deviceId.value;

  const results = await Promise.all([
    editForm.name !== device.value?.name ? devicesStore.updateDeviceName(id, editForm.name) : { ok: true },
    editForm.description !== device.value?.description ? devicesStore.updateDeviceDescription(id, editForm.description) : { ok: true },
    editForm.alias !== device.value?.alias ? devicesStore.updateDeviceAlias(id, editForm.alias) : { ok: true },
  ]);

  editLoading.value = false;

  const failed = results.find((r) => !r.ok);
  if (failed) {
    editError.value = failed.error?.message || "Failed to update device";
    return;
  }

  showEditModal.value = false;
  toast.success({ title: "Updated", text: "Device updated successfully" });
}

function openAssign() {
  openAssignModal(device.value?.area_id);
}

async function handleAssignSubmit() {
  const result = await submitAssignCore(deviceId.value, devicesStore.assignToArea.bind(devicesStore));
  if (result?.ok) {
    toast.success({ title: "Assigned", text: "Device assigned to area successfully" });
  }
}

function openUnassign() {
  if (!device.value) return;
  unassignDialogMessage.value = `Are you sure you want to unassign device "${device.value.name || device.value.alias}" from its area?`;
  unassignError.value = "";
  showUnassignDialog.value = true;
}

async function submitUnassign() {
  if (!device.value) return;
  unassignLoading.value = true;
  unassignError.value = "";

  const result = await devicesStore.unassignDevice(deviceId.value);
  unassignLoading.value = false;

  if (!result.ok) {
    unassignError.value = result.error?.message || "Failed to unassign device";
    return;
  }

  showUnassignDialog.value = false;
  toast.success({ title: "Unassigned", text: "Device unassigned from area successfully" });
}

function remove() {
  if (!device.value) return;
  removeDialogMessage.value = `Are you sure you want to remove device "${device.value.name || device.value.alias}"?`;
  removeError.value = "";
  showRemoveDialog.value = true;
}

async function submitRemove() {
  const id = deviceId.value;
  removeLoading.value = true;
  removeError.value = "";

  const result = await devicesStore.removeDevice(id);
  removeLoading.value = false;

  if (!result.ok) {
    removeError.value = result.error?.message || "Failed to remove device";
    return;
  }

  showRemoveDialog.value = false;
  toast.success({ title: "Removed", text: "Device removed successfully" });
  router.push({ name: "devices" });
}

async function reboot() {
  if (!device.value) return;

  const result = await devicesStore.rebootDevice(device.value.id);

  if (!result.ok) {
    toast.error({ title: "Reboot failed", text: result.error?.message || "Failed to reboot device" });
  } else {
    toast.success({ title: "Rebooting", text: `Device ${device.value.name || device.value.alias || "#" + device.value.id} is rebooting` });
  }
}

function openResetup() {
  if (!device.value) return;
  resetupDialogMessage.value = `Are you sure you want to repeat setup for device "${device.value.name || device.value.alias}"?`;
  resetupError.value = "";
  showResetupDialog.value = true;
}

async function submitResetup() {
  const id = deviceId.value;
  resetupLoading.value = true;
  resetupError.value = "";

  const result = await devicesStore.resetupDevice(id);
  resetupLoading.value = false;

  if (!result.ok) {
    resetupError.value = result.error?.message || "Failed to repeat device setup";
    return;
  }

  showResetupDialog.value = false;
  toast.success({ title: "Success", text: `Device ${device.value?.name || device.value?.alias || "#" + id} setup repeated` });
  router.push({ name: "devices" });
}

function openReset() {
  if (!device.value) return;
  resetDialogMessage.value = `Are you sure you want to reset device "${device.value.name || device.value.alias}"?`;
  resetError.value = "";
  showResetDialog.value = true;
}

async function submitReset() {
  const id = deviceId.value;
  resetLoading.value = true;
  resetError.value = "";

  const result = await devicesStore.resetDevice(id);
  resetLoading.value = false;

  if (!result.ok) {
    resetError.value = result.error?.message || "Failed to reset device";
    return;
  }

  showResetDialog.value = false;
  toast.success({ title: "Success", text: `Device ${device.value?.name || device.value?.alias || "#" + id} reset` });
  router.push({ name: "devices" });
}

function openFirmwareUpdate() {
  selectedFirmwareId.value = compatibleFirmwares.value[0]?.id || null;
  firmwareUpdateError.value = "";
  showFirmwareUpdateModal.value = true;
}

async function submitFirmwareUpdate() {
  if (!selectedFirmwareId.value || !device.value) return;
  const result = await firmwaresStore.updateDeviceFirmware(device.value.id, selectedFirmwareId.value);
  if (!result.ok) {
    firmwareUpdateError.value = result.error?.message || "Firmware update failed";
    return;
  }
  showFirmwareUpdateModal.value = false;
  toast.success({ title: "Updated", text: "Firmware update pushed successfully" });
  await devicesStore.loadDeviceDetail(deviceId.value);
}

function systemStatusVariant(status) {
  const map = {
    active: "success",
    removed: "danger",
    freezed: "warning",
    setup: "primary",
  };
  return map[status] || "secondary";
}

async function loadStatus() {
  const id = deviceId.value;
  if (!id || !device.value) return;
  if (device.value.connection_status !== "active") return;

  isLoadingStatus.value = true;
  statusError.value = null;

  const result = await devicesStore.loadDeviceStatus(id);

  isLoadingStatus.value = false;

  if (!result.ok) {
    statusError.value = result.error;
  }
}

async function init() {
  const id = deviceId.value;
  if (!id) return;

  if (areasStore.areas.length === 0) {
    await areasStore.loadAreas();
  }

  await devicesStore.loadDeviceDetail(id);

  if (device.value?.connection_status === "active") {
    await loadStatus();
    await firmwaresStore.loadDeviceCompatibility(id);
  }
}

onMounted(() => {
  init();
});

onUnmounted(() => {
  devicesStore.clearDeviceDetail();
  firmwaresStore.clearCompatibility();
});

watch(() => route.params.id, (newId, oldId) => {
  if (newId !== oldId) {
    devicesStore.clearDeviceDetail();
    init();
  }
});
</script>

<style scoped>
.device-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 24px;
}

.script-info-panel {
  display: grid;
  gap: 8px;
  padding: 12px;
  background: var(--color-panel);
  border: 1px solid rgba(192, 202, 245, 0.12);
  margin-bottom: 24px;
}

.info-row {
  display: flex;
  gap: 8px;
  align-items: baseline;
}

.info-label {
  font-size: 12px;
  text-transform: uppercase;
  min-width: 48px;
}

.info-value {
  font-size: 13px;
  word-break: break-all;
}

.devices-panel {
  margin-bottom: 24px;
}

.block-title {
  font-weight: 700;
  text-transform: uppercase;
  margin-bottom: 12px;
  color: var(--color-primary);
}

.form-group {
  margin-bottom: 16px;
}

.firmware-options {
  display: grid;
  gap: 8px;
  margin: 12px 0;
}

.firmware-option {
  padding: 10px 12px;
  border: 1px solid rgba(192, 202, 245, 0.12);
  border-radius: 6px;
  cursor: pointer;
  background: var(--color-panel);
}

.firmware-option.active {
  border-color: var(--color-primary);
  background: rgba(59, 130, 246, 0.1);
}

.fw-version {
  font-weight: 600;
  font-size: 13px;
}

.fw-desc {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 2px;
}
</style>
