<template>
  <div>
    <div class="page-header">
      <h2>{{ isEdit ? 'Edit PC' : 'New PC' }}</h2>
    </div>

    <div class="card">
      <div v-if="loading" class="loading">Loading...</div>

      <form v-else @submit.prevent="savePC">
        <div class="form-row">
          <div class="form-group">
            <label for="machinenumber">PC Number *</label>
            <input
              id="machinenumber"
              v-model="form.machinenumber"
              type="text"
              class="form-control"
              required
              @input="onPcNumberInput"
            />
            <small class="form-hint">Defaults to the serial number; editable</small>
          </div>

          <div class="form-group">
            <label for="alias">Alias</label>
            <input
              id="alias"
              v-model="form.alias"
              type="text"
              class="form-control"
            />
          </div>
        </div>

        <div class="form-row">
          <div class="form-group" v-if="isEnabled('fqdn', 'computer')">
            <label for="hostname">Hostname</label>
            <input
              id="hostname"
              v-model="form.hostname"
              type="text"
              class="form-control"
            />
          </div>

          <div class="form-group">
            <label for="serialnumber">Serial Number</label>
            <input
              id="serialnumber"
              v-model="form.serialnumber"
              type="text"
              class="form-control"
            />
          </div>
        </div>

        <div class="form-row" v-if="isEnabled('gaugelabreference', 'computer') || isEnabled('maintenancereference', 'computer')">
          <div class="form-group" v-if="isEnabled('gaugelabreference', 'computer')">
            <label for="gaugelabreference">Gauge Lab Reference</label>
            <input
              id="gaugelabreference"
              v-model="form.gaugelabreference"
              type="text"
              class="form-control"
            />
          </div>

          <div class="form-group" v-if="isEnabled('maintenancereference', 'computer')">
            <label for="maintenancereference">Maintenance Reference</label>
            <input
              id="maintenancereference"
              v-model="form.maintenancereference"
              type="text"
              class="form-control"
            />
          </div>
        </div>

        <div class="form-row">
          <div class="form-group">
            <label for="machinetypeid">PC Type *</label>
            <select
              id="machinetypeid"
              v-model="form.machinetypeid"
              class="form-control"
              required
              @change="form.modelnumberid = ''"
            >
              <option value="">Select type...</option>
              <option
                v-for="pt in pcTypes"
                :key="pt.computertypeid"
                :value="pt.computertypeid"
              >
                {{ pt.computertype }}
              </option>
            </select>
          </div>

          <div class="form-group">
            <label for="osid">Operating System</label>
            <select
              id="osid"
              v-model="form.osid"
              class="form-control"
            >
              <option value="">Select OS...</option>
              <option
                v-for="os in operatingsystems"
                :key="os.osid"
                :value="os.osid"
              >
                {{ os.osname }}
              </option>
            </select>
          </div>
        </div>

        <div class="form-row">
          <div class="form-group">
            <label for="statusid">Status</label>
            <select
              id="statusid"
              v-model="form.statusid"
              class="form-control"
            >
              <option value="">Select status...</option>
              <option
                v-for="s in statuses"
                :key="s.statusid"
                :value="s.statusid"
              >
                {{ s.status }}
              </option>
            </select>
          </div>

          <div class="form-group">
            <label for="locationid">Location</label>
            <select
              id="locationid"
              v-model="form.locationid"
              class="form-control"
            >
              <option value="">Select location...</option>
              <option
                v-for="l in locations"
                :key="l.locationid"
                :value="l.locationid"
              >
                {{ l.locationname }}
              </option>
            </select>
          </div>
        </div>

        <div class="form-row">
          <div class="form-group">
            <label for="vendorid">Vendor</label>
            <select
              id="vendorid"
              v-model="form.vendorid"
              class="form-control"
              @change="form.modelnumberid = ''"
            >
              <option value="">Select vendor...</option>
              <option
                v-for="v in vendors"
                :key="v.vendorid"
                :value="v.vendorid"
              >
                {{ v.vendor }}
              </option>
            </select>
          </div>

          <div class="form-group">
            <label for="modelnumberid">Model</label>
            <select
              id="modelnumberid"
              v-model="form.modelnumberid"
              class="form-control"
            >
              <option value="">Select model...</option>
              <option
                v-for="m in filteredModels"
                :key="m.modelnumberid"
                :value="m.modelnumberid"
              >
                {{ m.modelnumber }}
              </option>
            </select>
            <small v-if="!form.vendorid && !form.machinetypeid" class="form-hint">
              Select vendor or PC type to filter models
            </small>
          </div>
        </div>

        <!-- PC-specific fields -->
        <h4 style="margin-top: 1.5rem; margin-bottom: 1rem;">Network Settings</h4>

        <div class="form-row">
          <div class="form-group">
            <label for="ipaddress">IP Address</label>
            <input
              id="ipaddress"
              v-model="form.ipaddress"
              type="text"
              class="form-control"
              placeholder="e.g., 192.168.1.100"
            />
          </div>

          <div class="form-group">
            <label for="loggedinuser">Logged In User</label>
            <input
              id="loggedinuser"
              v-model="form.loggedinuser"
              type="text"
              class="form-control"
            />
          </div>
        </div>

        <div class="form-group">
          <label>Remote Access Protocols</label>
          <div class="protocol-list">
            <label v-for="p in protocols" :key="p.protocolid" class="protocol-item">
              <input type="checkbox" :checked="isProtocolOn(p.protocolid)" @change="toggleProtocol(p.protocolid, $event.target.checked)" />
              <span>{{ p.name }}</span>
              <input
                v-if="isProtocolOn(p.protocolid)"
                type="number"
                class="port-override"
                :value="protocolPort(p.protocolid)"
                :placeholder="p.defaultport || 'port'"
                min="1"
                max="65535"
                title="Port override (blank = default)"
                @input="setProtocolPort(p.protocolid, $event.target.value)"
              />
            </label>
            <span v-if="!protocols.length" class="muted">No protocols defined. Add them under Settings &gt; PC Access Protocols.</span>
          </div>
        </div>

        <!-- Printers assigned to this PC ITSELF, which replace whatever the
             machine it controls is assigned. Same component the machine form
             uses: two copies of this UI would drift, and the two ends of an
             override disagreeing is the bug nobody would spot. -->
        <PrinterAssignmentPicker ref="printerPickerRef" :assetid="currentAssetId" scope="pc" />

        <div class="form-group">
          <label for="notes">Notes</label>
          <textarea
            id="notes"
            v-model="form.notes"
            class="form-control"
            rows="3"
          ></textarea>
        </div>

        <!-- Map Location Picker -->
        <div class="form-group">
          <label>Map Location</label>
          <div class="map-location-control">
            <div v-if="form.mapx !== null && form.mapy !== null" class="current-position">
              Position: {{ form.mapx }}, {{ form.mapy }}
                <span v-if="form.levelid" class="position-level">on {{ levelName(form.levelid) }}</span>
                <span v-else class="position-level position-level-missing">level not set</span>
              <button type="button" class="btn btn-sm btn-secondary" @click="clearMapPosition">Clear</button>
            </div>
            <button type="button" class="btn btn-secondary" @click="openMapPicker">
              Set Location on Map
            </button>
          </div>
        </div>

        <!-- Map Picker Modal -->
        <Modal v-model="showMapPicker" title="Select Location on Map" size="fullscreen">
          <div class="map-modal-content">
            <div v-if="levelOptions().length > 1" class="map-level-picker">
              <label>Level</label>
              <select v-model.number="pickerLevelId" class="form-control">
                <option v-for="option in levelOptions()" :key="option.levelid"
                        :value="option.levelid">{{ option.label }}</option>
              </select>
              <span class="input-hint">
                The position is pixels on this drawing, so pick the level first.
              </span>
            </div>
            <ShopFloorMap
              :pickerMode="true"
              :levelid="pickerLevelId"
              :initialPosition="form.mapx !== null ? { left: form.mapx, top: form.mapy } : null"
              :theme="currentTheme"
              @positionPicked="handlePositionPicked"
            />
          </div>
          <template #footer>
            <button class="btn btn-secondary" @click="showMapPicker = false">Cancel</button>
            <button class="btn btn-primary" @click="confirmMapPosition">Confirm Location</button>
          </template>
        </Modal>

        <!-- Site-defined custom fields for computers -->
        <CustomFieldsInputs ref="customFieldsRef" :assettypeid="COMPUTER_ASSETTYPEID" :assetid="currentAssetId" />

        <div v-if="error" class="error-message">{{ error }}</div>

        <div style="display: flex; gap: 0.5rem; margin-top: 1.5rem;">
          <button type="submit" class="btn btn-primary" :disabled="saving">
            {{ saving ? 'Saving...' : 'Save PC' }}
          </button>
          <router-link to="/pcs" class="btn btn-secondary">Cancel</router-link>
        </div>
      </form>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { computersApi, assetsApi, vendorsApi, locationsApi, modelsApi, operatingsystemsApi,
  printersApi, relationshipTypesApi } from '@/api'
import ShopFloorMap from '@/components/ShopFloorMap.vue'
import { loadMapConfig, levelOptions, levelName, state as mapConfig }
  from '@/composables/mapConfig'
import Modal from '@/components/Modal.vue'
import CustomFieldsInputs from '@/components/CustomFieldsInputs.vue'
import PrinterAssignmentPicker from '@/components/PrinterAssignmentPicker.vue'
import { currentTheme } from '@/stores/theme'
import { useIdentifierFlags } from '@/composables/identifierSettings'
import { isPluginEnabled, loadEnabledPlugins } from '@/composables/enabledPlugins'
import { useToast } from '@/composables/toast'
import { apiError } from '@/utils/apiError'

const toast = useToast()
const { isEnabled } = useIdentifierFlags()

const route = useRoute()
const router = useRouter()

const isEdit = computed(() => !!route.params.id)

// Seeded asset-type id for computers (see /api/assets/types). Custom-field
// values are keyed by the underlying asset id, captured on load / create.
const COMPUTER_ASSETTYPEID = 2
const customFieldsRef = ref(null)
const printerPickerRef = ref(null)
const currentAssetId = ref(null)

// PC Number (assetnumber) defaults to the serial number while the user hasn't
// typed their own. Editable; only auto-fills on a new PC.
const manualPcNumber = ref(false)
function onPcNumberInput() {
  manualPcNumber.value = true
}

const loading = ref(true)
const saving = ref(false)
const error = ref('')
const showMapPicker = ref(false)
// Which drawing the picker shows, and therefore which level the coordinates it
// returns belong to (ADR-017). Opens on the position's existing level so editing
// a marker does not silently move it to the default one.
const pickerLevelId = ref(null)
const tempMapPosition = ref(null)

const form = ref({
  machinenumber: '',
  alias: '',
  hostname: '',
  serialnumber: '',
  gaugelabreference: '',
  maintenancereference: '',
  machinetypeid: '',
  statusid: '',
  vendorid: '',
  modelnumberid: '',
  locationid: '',
  osid: '',
  loggedinuser: '',
  accessmethods: [],
  notes: '',
  mapx: null,
  mapy: null,
  levelid: null,
  ipaddress: ''
})

const pcTypes = ref([])
const protocols = ref([])
const statuses = ref([])

// Access-method editor helpers (form.accessmethods = [{protocolid, portoverride}])
function isProtocolOn(protocolid) {
  return form.value.accessmethods.some(a => a.protocolid === protocolid)
}
function protocolPort(protocolid) {
  const found = form.value.accessmethods.find(a => a.protocolid === protocolid)
  return found && found.portoverride != null ? found.portoverride : ''
}
function toggleProtocol(protocolid, on) {
  if (on) {
    if (!isProtocolOn(protocolid)) {
      form.value.accessmethods.push({ protocolid, portoverride: null })
    }
  } else {
    form.value.accessmethods = form.value.accessmethods.filter(a => a.protocolid !== protocolid)
  }
}
function setProtocolPort(protocolid, value) {
  const found = form.value.accessmethods.find(a => a.protocolid === protocolid)
  if (found) {
    const n = parseInt(value, 10)
    found.portoverride = Number.isFinite(n) ? n : null
  }
}
const vendors = ref([])
const models = ref([])
const locations = ref([])
const operatingsystems = ref([])


// Default PC Number to serial while the user hasn't typed their own (new PC only)
watch(() => form.value.serialnumber, (serial) => {
  if (!isEdit.value && !manualPcNumber.value && serial) {
    form.value.machinenumber = serial
  }
})

// Filter models by selected vendor and PC type
const filteredModels = computed(() => {
  // filter by vendor only (PC type now maps to computertypeid, a different id
  // space than a model's machinetypeid)
  if (!form.value.vendorid) return models.value
  return models.value.filter(m => m.vendorid === form.value.vendorid)
})

onMounted(async () => {
  try {
    // Load reference data
    // perpage 100 so dropdowns aren't truncated to the default 20-row page
    const [ptRes, statusRes, vendorRes, allModels, locRes, osRes, protoRes] = await Promise.all([
      computersApi.types.list({ perpage: 100 }),
      assetsApi.statuses.list(),
      vendorsApi.list({ perpage: 100 }),
      modelsApi.listAll(),  // backend caps perpage at 100; page through all
      locationsApi.list({ perpage: 100 }),
      operatingsystemsApi.list({ perpage: 100 }),
      computersApi.protocols.list(),
      // Handles its own failure: a site without printers still gets a form.
    ])

    pcTypes.value = ptRes.data.data || []
    statuses.value = statusRes.data.data || []
    vendors.value = vendorRes.data.data || []
    models.value = allModels
    locations.value = locRes.data.data || []
    operatingsystems.value = osRes.data.data || []
    protocols.value = protoRes.data.data || []

    // Load PC if editing (asset-based shape: extension under pc.computer)
    if (isEdit.value) {
      const response = await computersApi.get(route.params.id)
      const pc = response.data.data
      const ext = pc.computer || {}
      currentAssetId.value = pc.assetid || null

      const primaryComm = pc.communications?.find(c => c.isprimary) || pc.communications?.[0]

      form.value = {
        machinenumber: pc.assetnumber || '',
        alias: pc.name && pc.name.toUpperCase() !== 'NONE' ? pc.name : '',
        hostname: ext.hostname || '',
        serialnumber: pc.serialnumber || '',
        gaugelabreference: pc.gaugelabreference || '',
        maintenancereference: pc.maintenancereference || '',
        machinetypeid: ext.computertypeid || '',
        statusid: pc.statusid || '',
        vendorid: ext.vendorid || '',
        modelnumberid: ext.modelnumberid || '',
        locationid: pc.locationid || '',
        osid: ext.osid || '',
        loggedinuser: ext.loggedinuser || '',
        accessmethods: (pc.accessmethods || []).map(a => ({
          protocolid: a.protocolid,
          portoverride: a.portoverride ?? null
        })),
        notes: pc.notes || '',
        mapx: pc.mapx ?? null,
        mapy: pc.mapy ?? null,
        levelid: pc.levelid ?? null,
        ipaddress: primaryComm?.ipaddress || ''
      }
    }
  } catch (err) {
    console.error('Error loading data:', err)
    error.value = 'Failed to load data'
  } finally {
    loading.value = false
  }
})

function handlePositionPicked(position) {
  tempMapPosition.value = position
}

function openMapPicker() {
  loadMapConfig().then(() => {
    pickerLevelId.value = form.value.levelid || mapConfig.defaultlevelid
    showMapPicker.value = true
  })
}

function confirmMapPosition() {
  if (tempMapPosition.value) {
    form.value.mapx = tempMapPosition.value.left
    form.value.mapy = tempMapPosition.value.top
    // Never one without the other: coordinates saved with no level render as
    // "level unknown", and coordinates saved against the wrong level render
    // convincingly in the wrong place.
    form.value.levelid = pickerLevelId.value
  }
  showMapPicker.value = false
}

function clearMapPosition() {
  form.value.mapx = null
  form.value.mapy = null
  form.value.levelid = null
  tempMapPosition.value = null
}

async function savePC() {
  error.value = ''
  saving.value = true

  try {
    // One payload for the computers plugin (asset core + computer extension +
    // primary IP). "PC Number" is the business identifier (assetnumber).
    const payload = {
      assetnumber: form.value.machinenumber,
      hostname: form.value.hostname || null,
      serialnumber: form.value.serialnumber || null,
      gaugelabreference: form.value.gaugelabreference || null,
      maintenancereference: form.value.maintenancereference || null,
      computertypeid: form.value.machinetypeid || null,
      statusid: form.value.statusid || null,
      vendorid: form.value.vendorid || null,
      modelnumberid: form.value.modelnumberid || null,
      locationid: form.value.locationid || null,
      osid: form.value.osid || null,
      loggedinuser: form.value.loggedinuser || null,
      accessmethods: form.value.accessmethods,
      notes: form.value.notes || null,
      ipaddress: form.value.ipaddress || null,
      mapx: form.value.mapx,
      mapy: form.value.mapy
    }
    // only set display name when an alias is given, so we don't clobber it
    if (form.value.alias) {
      payload.name = form.value.alias
    }

    let assetId = currentAssetId.value
    if (isEdit.value) {
      const response = await computersApi.update(route.params.id, payload)
      assetId = assetId || response.data?.data?.assetid || response.data?.data?.asset?.assetid
    } else {
      const response = await computersApi.create(payload)
      assetId = response.data?.data?.assetid || response.data?.data?.asset?.assetid
    }

    // Persist any custom-field values now that we have an asset id.
    if (assetId && customFieldsRef.value) {
      try {
        await customFieldsRef.value.save(assetId)
      } catch (cfErr) {
        console.error('Error saving custom fields:', cfErr)
      }
    }

    // Printer assignment through the shared picker, which reconciles the whole
    // set in one call rather than row at a time.
    //
    // Toasted, not thrown: the PC itself is saved by now, so staying on a form
    // whose Save would create a second PC is the worse failure - but an
    // assignment that quietly did not happen is the bug this feature exists to
    // stop, so it has to be said out loud.
    if (assetId && printerPickerRef.value) {
      try {
        await printerPickerRef.value.save(assetId)
      } catch (printerError) {
        console.error('Error saving printer assignment:', printerError)
        toast.error(apiError(printerError, 'PC saved, but the printer assignment did not'))
      }
    }

    router.push('/pcs')
  } catch (err) {
    console.error('Error saving PC:', err)
    error.value = apiError(err, 'Failed to save PC')
  } finally {
    saving.value = false
  }
}
</script>

<style scoped>
.protocol-list {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}
.protocol-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.protocol-item .port-override {
  width: 78px;
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}
.muted {
  color: var(--text-light);
}

/* Scrolls rather than pushing the rest of the form off screen: a site can hold
   dozens of printers. */
.printer-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
  margin-top: 0.5rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}
.printer-item {
  display: flex;
  align-items: center;
  gap: 8px;
}
.printer-meta {
  color: var(--text-light);
  font-size: 0.85rem;
}

.map-location-control {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.current-position {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: monospace;
  color: var(--text);
}

.map-modal-content {
  height: calc(90vh - 140px);
}

.map-modal-content :deep(.shopfloor-map) {
  height: 100%;
}

.map-modal-content :deep(.map-container) {
  height: calc(100% - 50px);
}

.form-hint {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.8rem;
  color: var(--text-light, #666);
}
</style>
