<template>
  <a-drawer
    title="计划执行日历"
    width="80vw"
    :visible="visible"
    @close="onClose"
    :closable="true"
    :maskClosable="true"
  >
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="fetchData">
        <a-row :gutter="24">
          <a-col :xl="12" :lg="12" :md="12" :sm="24">
            <a-form-item label="日期">
              <a-date-picker valueFormat="YYYY-MM-DD" placeholder="请选择开始日期" class="query-group-cust" v-model="params.calMonthStart"></a-date-picker>
              <span class="query-group-split-cust"></span>
              <a-date-picker valueFormat="YYYY-MM-DD" placeholder="请选择结束日期" class="query-group-cust" v-model="params.calMonthEnd"></a-date-picker>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="fetchData" icon="search">查询</a-button>
              <a-button type="primary" @click="exportToExcel" icon="download" style="margin-left: 8px">导出Excel</a-button>
              <a-button @click="restoreQuery" icon="reload" style="margin-left: 8px">重置</a-button>
              <a-button type="primary" @click="createPlan" v-has="'plan:create'" icon="plus" style="margin-left: 8px">临时计划</a-button>
              <a-button type="primary" @click="handleAdd" v-has="'plan:create'" icon="plus" class="orange-btn">自动排产</a-button>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <a-table
      ref="table"
      :columns="columns"
      :dataSource="deviceData"
      :scroll="{ x: 'max-content' }"
      rowKey="id"
      bordered
      :loading="loading"
      size="middle"
    >
      <template slot="deviceName" slot-scope="text,record">
        <div>
          {{record.deviceName}}({{record.deviceCode}})
        </div>
      </template>
    </a-table>

    <a-modal
      title="新增计划"
      :visible="modelVisible"
      @ok="handleSubmit"
      @cancel="closeModel"
    >
      <a-form :form="modelForm" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" >
        <a-form-item label="计划日期">
          <a-date-picker format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" v-model="modelForm.calDay" />
        </a-form-item>
        <a-form-item label="检修任务">
          <j-dict-select-tag placeholder="要生成计划的修程" dict-code="repair_range" v-model="modelForm.rapairRange" />
        </a-form-item>
        <a-form-item label="设备">
          <j-search-select-tag placeholder="要生成计划的设备" dict="v_bu_device,name,id" v-model="modelForm.deviceId" />
        </a-form-item>
      </a-form>
    </a-modal>
    <plan-modal ref="modalForm"></plan-modal>
    <work-order-modal v-if="workOrderVisible" ref="workOrderModal" @ok="closeWorkOrder" @close="closeWorkOrder"></work-order-modal>
  </a-drawer>
</template>

<script>
import moment from 'moment';
import ExcelJS from 'exceljs';
import { formatDate1, getDateRange } from '@/utils/util'
import { getAction, postAction } from '@/api/manage'
import WorkOrderModal from '@views/workOrder/modules/WorkOrderModal.vue'
import PlanModal from '@views/plan/modules/PlanModal.vue'

export default {
  name: 'PlanCalendarChart',
  components: { PlanModal, WorkOrderModal },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      planId: null,
      workOrderVisible: false,
      deviceData: [],
      dateRange: [],
      columns: [],
      params: {
        calMonthStart: '',
        calMonthEnd: ''
      },
      loading: false,
      modelVisible: false,
      modelForm: {},
      // defaultDay: '',
      dragItem: null,
    }
  },
  watch: {
    visible(newVal, oldVal) {
      if(newVal) this.restoreQuery()
    }
  },
  methods: {
    async fetchData() {
      // 更新 dateRange
      const start = new Date(this.params.calMonthStart);
      const end = new Date(this.params.calMonthEnd);
      this.dateRange = getDateRange(this.params.calMonthStart, this.dateDiff(start, end) + 1);

      const devices = await this.loadDevice();
      const statusList = await  this.loadData();

      // 生成 statusMap[deviceId][date] = 状态
      const statusMap = {}
      statusList.forEach(s => {
        if (!statusMap[s.deviceId]) statusMap[s.deviceId] = {}
        statusMap[s.deviceId][s.calDay] = s
      })

      // 构造设备数据，每个设备带有 statusMap
      this.deviceData = devices.map(device => ({
        ...device,
        statusMap: statusMap[device.id] || {},
      }))

      // 构造表格列
      this.buildColumns()
      this.$nextTick(() => this.bindTdEvents()); // 绑定 drop 到 td
    },
    // 获取设备列表
    loadDevice() {
      return getAction('/device/buDevice/list', {
        pageNo: 1,
        pageSize: 10000,
      }).then(res => {
        if (res.success) return res.result.records || res.result
        this.$message.warning(res.message || '获取设备失败')
        return []
      })
    },
    // 获取检修计划数据
    loadData() {
      this.loading = true;
      return getAction('/plan/plan/list', this.params).then(res => {
        if (res.success) {
          this.loading = false;
          return res.result.records || res.result
        }
        this.$message.warning(res.message || '获取状态失败')
        this.loading = false;
        return []
      })
    },
    // 列构建逻辑
    buildColumns() {
      const todayStr = new Date().toLocaleDateString('sv-SE');
      this.columns = [
        {
          title: '设备名称',
          dataIndex: 'deviceName',
          fixed: 'left',
          scopedSlots: { customRender: 'deviceName' },
        },
        ...this.dateRange.map(date => ({
          key: date,
          width: '100px',
          title: () => {
            const weekday = this.getWeekday(date) // 如：'周六'
            const isWeekend = weekday === '星期六' || weekday === '星期天'
            return this.$createElement(
              'div',
              {
                style: {
                  color: isWeekend ? 'red' : date===todayStr ? '#9a00ff' : '#333',
                  fontWeight: date===todayStr ? 'bolder' : 'normal',
                  fontSize: '14px',
                  textAlign: 'center',
                }
              },
              `${date} (${weekday})`
            );
          },
          customRender: row => {
            const status = (row.statusMap[date] && row.statusMap[date].rapairRange_dictText) || '';
            const bgColor = this.getStatusColor(status);
            return this.$createElement(
              'div',
              {
                style: {
                  background: bgColor,
                  color: '#fff',
                  textAlign: 'center',
                  padding: '4px',
                  borderRadius: '4px',
                  fontSize: '14px',
                  minHeight: '30px',
                  cursor: status ? 'move' : 'default',
                  boxShadow: (date === todayStr && status) ? '0 0 0 3px #a09fa1 inset' : 'none',
                },
                attrs: {
                  draggable: !!status,  // 只有有状态的单元格才可拖拽
                  'data-row-id': row.id,
                  'data-date': date,
                },
                on: status ? {
                  dblclick: () => this.createOrder(row.statusMap[date]),
                  // 拖拽逻辑
                  dragstart: e => status && (this.dragItem = row.statusMap[date]),
                } : {}
              },
              status || ''
            );
          },
        })),
      ]
    },
    // 获取日期之间的天数差
    dateDiff(startDate, endDate) {
      const diffTime = endDate.getTime() - startDate.getTime();
      return Math.floor(diffTime / (1000 * 3600 * 24));
    },
    getWeekday(dateStr) {
      const days = ['天', '一', '二', '三', '四', '五', '六'];
      const date = new Date(dateStr);
      return '星期' + days[date.getDay()];
    },
    getStatusColor(status) {
      const colorMap = {
        '周检': '#52c41a',
        '月检': '#fae457',
        '双月检': '#f89d1b',
        '三月检': '#fa6565',
        '半年检': '#64aaee',
        '年检': '#2741f3',
        '维修': '#fd0000',
        '巡检': '#28ff8c',
        '例行检查': '#1cffff',
        '专项修': '#bf1cff',
      };
      return colorMap[status] || 'transparent'
    },
    onClose() {
      this.$emit('close')
    },
    restoreQuery() {
      this.dateRange = getDateRange(new Date(), 30)
      this.params.calMonthStart = this.dateRange[0]
      this.params.calMonthEnd = this.dateRange[29]
      this.fetchData()
    },
    //从检修计划创建工单
    createOrder(item) {
      if (item.workOrder != null) {
        return;
      }
      this.planId = item.id;
      this.workOrderVisible = true;

      this.$nextTick(() => {
        this.$refs.workOrderModal.add(item);
        this.$refs.workOrderModal.title = "创建工单";
        this.$refs.workOrderModal.disableSubmit = false;
      })
    },
    closeWorkOrder() {
      this.planId = null;
      this.workOrderVisible = false;
    },
    createPlan() {
      this.modelForm = {
        calDay: moment().format('YYYY-MM-DD')
      }
      this.modelVisible = true;
    },
    handleSubmit(){
      postAction("/plan/plan/add", this.modelForm).then((res) => {
        if (res.success) {
          this.fetchData();
          this.modelVisible = false;
          this.$message.success(res.message);
        } else {
          this.$message.warning(res.message);
        }
      });
    },
    closeModel(){
      this.modelForm = {};
      this.modelVisible = false;
    },
    // 拖拽逻辑实现
    onDrop(e, td) {
      e.preventDefault();
      td.classList.remove('drag-over');

      if(!this.dragItem) return;

      const targetDeviceId = td.dataset.rowId;
      const targetDay = td.dataset.date;

      console.log('拖拽源：', this.dragItem);
      console.log('目标设备ID：', targetDeviceId, '日期：', targetDay);
      postAction('/plan/plan/movePlan', {
        id: this.dragItem.id,
        deviceId: targetDeviceId,
        calDay: targetDay,
      }).then(res => {
        if (res.success) {
          this.$message.success('移动成功');
          this.fetchData();
        } else {
          this.$message.error(res.message || '移动失败');
        }
      });

      this.dragItem = null;
    },
    bindTdEvents(){
      this.$nextTick(() => {
        const tds = this.$refs.table.$el.querySelectorAll('td');
        tds.forEach(td => {
          const div = td.querySelector('div[draggable]');
          if(!div) return;
          // 把 div 的 data-row-id 和 data-date 保存到 td.dataset
          td.dataset.rowId = div.getAttribute('data-row-id');
          td.dataset.date = div.getAttribute('data-date');

          td.addEventListener('dragover', e => e.preventDefault());
          td.addEventListener('drop', e => this.onDrop(e, td));
          td.addEventListener('dragenter', e => td.classList.add('drag-over'));
          td.addEventListener('dragleave', e => td.classList.remove('drag-over'));
        });
      });
    },
    handleAdd() {
      this.$refs.modalForm.add();
      this.$refs.modalForm.title = "新增";
      this.$refs.modalForm.disableSubmit = false;
    },
    async exportToExcel() {
      if (!this.dateRange || this.dateRange.length === 0) {
        this.$message.warning('请先查询数据');
        return;
      }
      if (!this.deviceData || this.deviceData.length === 0) {
        this.$message.warning('暂无数据可导出');
        return;
      }

      const workbook = new ExcelJS.Workbook();
      const worksheet = workbook.addWorksheet('计划执行日历');

      // === 1. 构建表头 ===
      const header = ['设备名称', '设备编号'];
      this.dateRange.forEach(date => {
        const weekday = this.getWeekday(date);
        header.push(`${date} (${weekday})`);
      });

      // 添加表头行
      const headerRow = worksheet.addRow(header);

      // 表头样式：加粗 + 背景灰 + 居中 + 自动换行（日期列需要）
      headerRow.eachCell((cell, colNumber) => {
        cell.font = { bold: true };
        cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFD3D3D3' } };
        cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: colNumber > 2 }; // 仅日期列换行
      });

      // === 2. 填充数据行 ===
      this.deviceData.forEach(device => {
        const row = [
          device.deviceName || '',
          device.deviceCode || ''
        ];
        this.dateRange.forEach(date => {
          const status = (device.statusMap[date] && device.statusMap[date].rapairRange_dictText) || '';
          row.push(status);
        });
        const excelRow = worksheet.addRow(row);

        // 为日期列设置颜色和自动换行
        this.dateRange.forEach((date, idx) => {
          const status = (device.statusMap[date] && device.statusMap[date].rapairRange_dictText) || '';
          const bgColor = this.getStatusColor(status);
          const cell = excelRow.getCell(idx + 3); // 第1列=设备名，第2列=编号，第3列起=日期

          // 设置内容对齐 + 自动换行
          cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };

          // 设置背景色（如果非透明）
          if (bgColor !== 'transparent') {
            cell.fill = {
              type: 'pattern',
              pattern: 'solid',
              fgColor: { argb: bgColor.replace('#', 'FF') }
            };
          }
        });

        // 设备名称列 & 编号列：禁止自动换行 + 左对齐（更美观）
        excelRow.getCell(1).alignment = { vertical: 'middle', horizontal: 'left', wrapText: false };
        excelRow.getCell(2).alignment = { vertical: 'middle', horizontal: 'left', wrapText: false };
      });

      // === 3. 设置列宽 ===
      worksheet.getColumn(1).width = 18; // 设备名称
      worksheet.getColumn(2).width = 18; // 设备编号
      for (let i = 3; i <= header.length; i++) {
        worksheet.getColumn(i).width = 15; // 日期列
      }

      // === 4. 下载文件 ===
      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      });
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = `计划执行日历_${new Date().toISOString().slice(0, 10)}.xlsx`;
      link.click();
      URL.revokeObjectURL(url);
    }
  },

}
</script>

<style scoped>
.drag-over {
  border: 2px dashed #1890ff !important;
}
.orange-btn {
  background-color: orange;
  border-color: orange;
  margin-left: 8px;
}
.orange-btn:hover {
  background-color: #f6cc7d;
  border-color: #f6cc7d;
}
</style>
