import { onMounted, reactive, ref } from 'vue/dist/vue.esm-bundler.js';
import { ElMessage, ElMessageBox } from 'element-plus';
import { createDeviceAsset, deleteDeviceAsset, listDeviceAssets, searchDeviceCompanyPersons, updateDeviceAsset } from './device-api-client.js';
import './device-asset.css';

/** File purpose: render device asset list, CRUD dialog, image thumbnail/original preview, and guarded deletion. */
export default {
  /** Plain purpose: create page state and all UI actions. Related files: device-api-client.js, DeviceAssetController.java. Flow: route -> setup -> API/form state -> Element Plus view. */
  setup() {
    const usageStatuses=['\u4f7f\u7528\u4e2d','\u95f2\u7f6e','\u7ef4\u4fee\u4e2d','\u505c\u7528'];
    const relationStatuses=['\u5df2\u5173\u8054','\u672a\u5173\u8054','\u5f85\u786e\u8ba4'];
    const loading=ref(false),saving=ref(false),dialogVisible=ref(false),editingId=ref(null),records=ref([]),total=ref(0),personOptions=ref([]),imageViewerVisible=ref(false),imageViewerUrl=ref('');
    const filters=reactive({page:1,size:20,deviceName:'',userPersonId:null,userUsageStatus:'',assetRelationStatus:''});
    const form=reactive(emptyForm());
    let searchTimer=null;

    /** Plain purpose: fetch the currently filtered device page. Related files: device-api-client.js, DeviceAssetService.java. Flow: page/filter event -> GET -> records/total -> table. */
    async function loadPage(){loading.value=true;try{const result=await listDeviceAssets(filters);records.value=result.records;total.value=result.total;}catch(error){ElMessage.error(error.message);}finally{loading.value=false;}}
    /** Plain purpose: return the create-form defaults that obey both dropdown rules. Related files: DeviceAssetSaveRequest.java, DeviceAssetView.js. Flow: create/reset -> defaults -> multipart POST. */
    function emptyForm(){return {deviceName:'',userPersonId:null,userUsageStatus:'\u4f7f\u7528\u4e2d',assetRelationStatus:'\u5f85\u786e\u8ba4',imageAttachment1:null,imageAttachment2:null,removeImageAttachment1:false,removeImageAttachment2:false,imageAttachment1Url:'',imageAttachment2Url:''};}
    /** Plain purpose: clear temporary preview URLs and restore a new-device form. Related files: DeviceAssetView.js, DeviceAssetFileStorageService.java. Flow: open create/save -> reset -> safe empty dialog. */
    function resetForm(){clearPreview('imageAttachment1');clearPreview('imageAttachment2');Object.assign(form,emptyForm());personOptions.value=[];}
    /** Plain purpose: show a fresh create dialog. Related files: DeviceAssetView.js, device-api-client.js. Flow: add button -> resetForm -> dialog. */
    function openCreate(){editingId.value=null;resetForm();dialogVisible.value=true;}
    /** Plain purpose: populate the dialog from one table row for editing. Related files: DeviceAssetResponse.java, DeviceAssetView.js. Flow: edit button -> row -> form -> PUT. */
    function openEdit(row){editingId.value=row.id;clearPreview('imageAttachment1');clearPreview('imageAttachment2');Object.assign(form,{...emptyForm(),deviceName:row.deviceName,userPersonId:row.userPersonId,userUsageStatus:row.userUsageStatus,assetRelationStatus:row.assetRelationStatus,imageAttachment1Url:row.imageAttachment1Url||'',imageAttachment2Url:row.imageAttachment2Url||''});personOptions.value=row.userPersonId?[{id:row.userPersonId,personName:row.userPersonName||`${'\u4eba\u5458'} ${row.userPersonId}`}]:[];dialogVisible.value=true;}
    /** Plain purpose: serialize form values and optional files to a multipart create/update request. Related files: device-api-client.js, DeviceAssetController.java. Flow: save -> FormData -> POST/PUT -> refresh table. */
    async function submitForm(){if(!form.deviceName.trim()){ElMessage.error('\u8bf7\u8f93\u5165\u8bbe\u5907\u540d\u79f0');return;}saving.value=true;try{const payload=new FormData();['deviceName','userPersonId','userUsageStatus','assetRelationStatus','removeImageAttachment1','removeImageAttachment2'].forEach(key=>{const value=form[key];if(value!==null&&value!==undefined&&value!=='')payload.append(key,value);});if(form.imageAttachment1)payload.append('imageAttachment1',form.imageAttachment1);if(form.imageAttachment2)payload.append('imageAttachment2',form.imageAttachment2);if(editingId.value===null)await createDeviceAsset(payload);else await updateDeviceAsset(editingId.value,payload);ElMessage.success(editingId.value===null?'\u65b0\u589e\u6210\u529f':'\u7f16\u8f91\u6210\u529f');dialogVisible.value=false;filters.page=1;await loadPage();}catch(error){ElMessage.error(error.message);}finally{saving.value=false;}}
    /** Plain purpose: ask for confirmation then request a reference-protected soft delete. Related files: device-api-client.js, DeviceAssetService.java. Flow: delete click -> confirm -> DELETE -> refresh or show error. */
    async function confirmDelete(row){try{await ElMessageBox.confirm(`\u786e\u8ba4\u5220\u9664\u8bbe\u5907\u201c${row.deviceName}\u201d\u5417\uff1f`,'\u5220\u9664\u786e\u8ba4',{type:'warning'});await deleteDeviceAsset(row.id);ElMessage.success('\u5220\u9664\u6210\u529f');if(records.value.length===1&&filters.page>1)filters.page-=1;await loadPage();}catch(error){if(error!=='cancel'&&error!=='close')ElMessage.error(error.message);}}
    /** Plain purpose: load active company people for the remote selector. Related files: device-api-client.js, DeviceAssetController.java. Flow: selector input -> lookup API -> dropdown options. */
    async function fetchPersonSuggestions(keyword){try{personOptions.value=await searchDeviceCompanyPersons(keyword);}catch(error){ElMessage.error(error.message);}}
    /** Plain purpose: reject unsupported or over-20MB files before uploading. Related files: DeviceAssetFileStorageService.java, DeviceAssetView.js. Flow: file choose -> local validation -> FormData or message. */
    function validateImageBeforeSelect(file){const raw=file.raw||file;if(!['image/jpeg','image/png','image/gif'].includes(raw.type)){ElMessage.error('\u4ec5\u652f\u6301 JPG\u3001PNG\u3001GIF \u56fe\u7247');return false;}if(raw.size>20*1024*1024){ElMessage.error('\u6bcf\u5f20\u56fe\u7247\u4e0d\u80fd\u8d85\u8fc7 20MB');return false;}return true;}
    /** Plain purpose: keep the selected original file and use a browser object URL for a scaled thumbnail preview. Related files: DeviceAssetFileStorageService.java, DeviceAssetView.js. Flow: upload component -> file/object URL -> preview and save. */
    function chooseImage(slot,file){if(!validateImageBeforeSelect(file))return false;clearPreview(slot);form[slot]=file.raw||file;form[`${slot}Url`]=URL.createObjectURL(form[slot]);form[`remove${slot.charAt(0).toUpperCase()+slot.slice(1)}`]=false;return false;}
    /** Plain purpose: release temporary object URLs so repeated edits do not retain browser memory. Related files: DeviceAssetView.js. Flow: replace/reset/remove -> clearPreview -> revokeObjectURL. */
    function clearPreview(slot){const url=form[`${slot}Url`];if(url&&url.startsWith('blob:'))URL.revokeObjectURL(url);}
    /** Plain purpose: mark an existing image reference for removal while preserving the historical original file on the server. Related files: DeviceAssetSaveRequest.java, DeviceAssetService.java. Flow: remove click -> multipart flag -> DB reference cleared. */
    function removeImage(slot){clearPreview(slot);form[slot]=null;form[`${slot}Url`]='';form[`remove${slot.charAt(0).toUpperCase()+slot.slice(1)}`]=true;}
    /** Plain purpose: open the original image in the viewer instead of generating a second thumbnail file. Related files: DeviceAssetResponse.java, DeviceAssetFileStorageService.java. Flow: thumbnail click -> controlled URL -> viewer. */
    function previewImage(url){if(url){imageViewerUrl.value=url;imageViewerVisible.value=true;}}
    /** Plain purpose: delay text filtering to avoid a request for every keystroke. Related files: DeviceAssetView.js, device-api-client.js. Flow: text input -> timer -> page reload. */
    function scheduleSearch(){window.clearTimeout(searchTimer);searchTimer=window.setTimeout(()=>{filters.page=1;loadPage();},300);}
    /** Plain purpose: apply the selected filters immediately from the first page. Related files: DeviceAssetPageQuery.java, DeviceAssetView.js. Flow: filter change -> page=1 -> GET -> table. */
    function submitSearch(){window.clearTimeout(searchTimer);filters.page=1;loadPage();}
    /** Plain purpose: remove every filter and reload the first page. Related files: DeviceAssetPageQuery.java, DeviceAssetView.js. Flow: reset -> default filters -> GET -> table. */
    function resetSearch(){window.clearTimeout(searchTimer);Object.assign(filters,{page:1,size:20,deviceName:'',userPersonId:null,userUsageStatus:'',assetRelationStatus:''});loadPage();}
    /** Plain purpose: switch to a requested page. Related files: DeviceAssetPageQuery.java, DeviceAssetView.js. Flow: pagination -> page -> GET. */
    function changePage(page){filters.page=page;loadPage();}
    /** Plain purpose: apply a new page size and return to page one. Related files: DeviceAssetPageQuery.java, DeviceAssetView.js. Flow: pagination -> size/page -> GET. */
    function changePageSize(size){filters.size=size;filters.page=1;loadPage();}
    /** Plain purpose: load the initial page when the routed component appears. Related files: DeviceAssetView.js, device-api-client.js. Flow: mount -> loadPage -> table. */
    onMounted(loadPage);
    return {usageStatuses,relationStatuses,loading,saving,dialogVisible,editingId,records,total,filters,form,personOptions,imageViewerVisible,imageViewerUrl,loadPage,openCreate,openEdit,submitForm,confirmDelete,fetchPersonSuggestions,chooseImage,removeImage,previewImage,scheduleSearch,submitSearch,resetSearch,changePage,changePageSize};
  },
  template:`<section class="device-asset-page"><header class="device-asset-page__header"><div><h2>&#x8bbe;&#x5907;&#x8d44;&#x4ea7;&#x7ba1;&#x7406;</h2><p>DEVICE ASSETS</p></div><el-button type="primary" @click="openCreate">&#x65b0;&#x589e;&#x8bbe;&#x5907;</el-button></header><section class="device-asset-page__panel"><el-form class="device-asset-page__filters" @submit.prevent="submitSearch"><el-input v-model="filters.deviceName" placeholder="&#x8bbe;&#x5907;&#x540d;&#x79f0;" @input="scheduleSearch"/><el-select v-model="filters.userPersonId" filterable remote clearable placeholder="&#x4f7f;&#x7528;&#x4eba;" :remote-method="fetchPersonSuggestions" @change="submitSearch"><el-option v-for="item in personOptions" :key="item.id" :label="item.personName" :value="item.id"/></el-select><el-select v-model="filters.userUsageStatus" clearable placeholder="&#x4f7f;&#x7528;&#x72b6;&#x6001;" @change="submitSearch"><el-option v-for="item in usageStatuses" :key="item" :label="item" :value="item"/></el-select><el-select v-model="filters.assetRelationStatus" clearable placeholder="&#x8d44;&#x4ea7;&#x5173;&#x8054;&#x72b6;&#x6001;" @change="submitSearch"><el-option v-for="item in relationStatuses" :key="item" :label="item" :value="item"/></el-select><el-button @click="resetSearch">&#x91cd;&#x7f6e;</el-button></el-form></section><section class="device-asset-page__panel"><el-table :data="records" v-loading="loading" empty-text="&#x6682;&#x65e0;&#x5339;&#x914d;&#x6570;&#x636e;"><el-table-column prop="id" label="ID" width="90"/><el-table-column prop="deviceName" label="&#x8bbe;&#x5907;&#x540d;&#x79f0;" min-width="180"/><el-table-column label="&#x56fe;&#x7247;" width="90"><template #default="{row}"><span v-if="!row.imageAttachment1Url">-</span><span v-else class="device-asset-page__image-cell"><img :src="row.imageAttachment1Url" @click="previewImage(row.imageAttachment1Url)"/></span></template></el-table-column><el-table-column label="&#x4f7f;&#x7528;&#x4eba;" min-width="160"><template #default="{row}">{{row.userPersonName?row.userPersonName+'('+row.userPersonId+')':(row.userPersonId?'--('+row.userPersonId+')':'-')}}</template></el-table-column><el-table-column prop="userUsageStatus" label="&#x4f7f;&#x7528;&#x72b6;&#x6001;" min-width="120"/><el-table-column prop="assetRelationStatus" label="&#x8d44;&#x4ea7;&#x5173;&#x8054;&#x72b6;&#x6001;" min-width="130"/><el-table-column prop="updateTime" label="&#x66f4;&#x65b0;&#x65f6;&#x95f4;" min-width="180"/><el-table-column label="&#x64cd;&#x4f5c;" width="150"><template #default="{row}"><el-button link @click="openEdit(row)">&#x7f16;&#x8f91;</el-button><el-button link type="danger" @click="confirmDelete(row)">&#x5220;&#x9664;</el-button></template></el-table-column></el-table><footer v-if="total" class="device-asset-page__pagination"><span>&#x5171; {{total}} &#x6761;</span><el-pagination layout="sizes, prev, pager, next" :current-page="filters.page" :page-size="filters.size" :page-sizes="[5,10,20,50]" :total="total" @current-change="changePage" @size-change="changePageSize"/></footer></section><el-dialog v-model="dialogVisible" :title="editingId===null?'\u65b0\u589e\u8bbe\u5907':'\u7f16\u8f91\u8bbe\u5907'" width="640px"><el-form label-position="top" @submit.prevent="submitForm"><el-row :gutter="16"><el-col :span="12"><el-form-item label="&#x8bbe;&#x5907;&#x540d;&#x79f0;" required><el-input v-model="form.deviceName"/></el-form-item></el-col><el-col :span="12"><el-form-item label="&#x4f7f;&#x7528;&#x4eba;"><el-select v-model="form.userPersonId" filterable remote clearable :remote-method="fetchPersonSuggestions" placeholder="&#x8f93;&#x5165;&#x4eba;&#x5458;&#x59d3;&#x540d;" style="width:100%"><el-option v-for="item in personOptions" :key="item.id" :label="item.personName" :value="item.id"/></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="&#x4f7f;&#x7528;&#x72b6;&#x6001;" required><el-select v-model="form.userUsageStatus" style="width:100%"><el-option v-for="item in usageStatuses" :key="item" :label="item" :value="item"/></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="&#x8d44;&#x4ea7;&#x5173;&#x8054;&#x72b6;&#x6001;" required><el-select v-model="form.assetRelationStatus" style="width:100%"><el-option v-for="item in relationStatuses" :key="item" :label="item" :value="item"/></el-select></el-form-item></el-col></el-row><div class="device-asset-page__images"><div v-for="slot in ['imageAttachment1','imageAttachment2']" :key="slot" class="device-asset-page__image-slot"><strong>{{slot==='imageAttachment1'?'\u56fe\u7247\u9644\u4ef6 1':'\u56fe\u7247\u9644\u4ef6 2'}}</strong><div class="device-asset-page__preview"><img v-if="form[slot+'Url']" :src="form[slot+'Url']" @click="previewImage(form[slot+'Url'])"/><span v-else>&#x6682;&#x65e0;&#x56fe;&#x7247;</span></div><el-upload :auto-upload="false" :show-file-list="false" :on-change="file=>chooseImage(slot,file)"><el-button size="small">&#x9009;&#x62e9;&#x56fe;&#x7247;</el-button></el-upload><el-button v-if="form[slot+'Url']" size="small" link type="danger" @click="removeImage(slot)">&#x79fb;&#x9664;</el-button></div></div></el-form><template #footer><el-button @click="dialogVisible=false">&#x53d6;&#x6d88;</el-button><el-button type="primary" :loading="saving" @click="submitForm">&#x4fdd;&#x5b58;</el-button></template></el-dialog><el-image-viewer v-if="imageViewerVisible" :url-list="[imageViewerUrl]" @close="imageViewerVisible=false"/></section>`
};
