<template>
  <div class="growth-record-view">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-content">
        <div class="header-title">
          <div class="title-icon-wrapper">
            <CameraOutlined class="title-icon" />
          </div>
          <div class="title-text">
            <h2>成长档案</h2>
            <p>记录学生的每一个成长瞬间</p>
          </div>
        </div>
        <div class="header-stats">
          <div class="stat-item">
            <span class="stat-value">{{ pagination.total }}</span>
            <span class="stat-label">档案总数</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 操作栏 -->
    <div class="action-bar">
      <div class="filters">
        <a-select v-model:value="filters.classId" placeholder="选择班级" allow-clear style="width: 150px;"
          @change="handleFilter">
          <a-select-option v-for="cls in myClasses" :key="cls.id" :value="cls.id">
            {{ cls.name }}
          </a-select-option>
        </a-select>
        <a-input-search v-model:value="filters.keyword" placeholder="搜索标题" style="width: 200px;" @search="handleFilter"
          allow-clear />
      </div>
      <a-button type="primary" class="add-btn" @click="showAddModal">
        <PlusOutlined class="btn-icon" />
        添加档案
      </a-button>
    </div>

    <!-- 档案卡片网格 -->
    <div class="record-grid" v-if="!loading && records.length > 0">
      <div v-for="record in records" :key="record.id" class="record-card">
        <div class="card-cover">
          <div v-if="record.images?.length" class="cover-image">
            <div class="image-wrapper">
              <a-spin :spinning="recordLoadingStates[record.id]" :indicator="null">
                <img
                  :src="getImageUrl(record.images[0])"
                  class="pos-absolute !object-contain"
                  :style="{ opacity: recordImageLoaded[record.id] ? 1 : 0, transition: 'opacity 0.3s' }"
                  @load="handleImageLoad(record.id)"
                  @error="handleImageError(record.id)"
                />
              </a-spin>
              <!-- 加载失败占位图 -->
              <div v-if="recordImageError[record.id]" class="error-placeholder">
                <FileTextOutlined class="placeholder-icon" />
              </div>
            </div>
            <div class="image-count" v-if="record.images.length > 1">
              <CameraOutlined /> {{ record.images.length }}
            </div>
          </div>
          <div v-else class="cover-placeholder">
            <FileTextOutlined class="placeholder-icon" />
          </div>
          <div class="type-badge" :class="record.recordType === 'STUDENT' ? 'personal' : 'class'">
            <UserOutlined v-if="record.recordType === 'STUDENT'" class="badge-icon" />
            <TeamOutlined v-else class="badge-icon" />
            {{ record.recordType === 'STUDENT' ? ' 个人' : ' 班级' }}
          </div>
        </div>
        <div class="card-body">
          <h3 class="record-title">{{ record.title }}</h3>
          <div class="record-meta">
            <div class="meta-item">
              <UserOutlined class="meta-icon" />
              <span>{{ record.student?.name || '班级档案' }}</span>
            </div>
            <div class="meta-item">
              <HomeOutlined class="meta-icon" />
              <span>{{ record.class?.name || '-' }}</span>
            </div>
            <div class="meta-item">
              <CalendarOutlined class="meta-icon" />
              <span>{{ formatDate(record.recordDate) }}</span>
            </div>
          </div>
          <p class="record-content">{{ record.content?.substring(0, 80) }}{{ record.content?.length > 80 ? '...' : '' }}
          </p>
        </div>
        <div class="card-actions">
          <a-button type="link" size="small" @click="handleView(record)">
            <EyeOutlined /> 查看
          </a-button>
          <a-button type="link" size="small" @click="handleEdit(record)">
            <EditOutlined /> 编辑
          </a-button>
          <a-popconfirm title="确定删除此档案？" @confirm="handleDelete(record.id)">
            <a-button type="link" size="small" danger>
              <DeleteOutlined /> 删除
            </a-button>
          </a-popconfirm>
        </div>
      </div>
    </div>

    <!-- 空状态 -->
    <div class="empty-state" v-if="!loading && records.length === 0">
      <div class="empty-icon-wrapper">
        <FileTextOutlined class="empty-icon" />
      </div>
      <p>暂无成长档案</p>
      <a-button type="primary" @click="showAddModal">
        创建第一份档案
      </a-button>
    </div>

    <!-- 加载状态 -->
    <div class="loading-state" v-if="loading">
      <a-spin size="large" />
      <p>加载中...</p>
    </div>

    <!-- 添加/编辑档案弹窗 -->
    <a-modal v-model:open="modalVisible" width="700px" @ok="handleModalOk" :confirm-loading="submitting">
      <template #title>
        <span class="modal-title">
          <EditOutlined v-if="isEdit" class="modal-title-icon" />
          <PlusOutlined v-else class="modal-title-icon" />
          {{ isEdit ? ' 编辑档案' : ' 添加档案' }}
        </span>
      </template>
      <a-form ref="formRef" :model="formState" :rules="rules" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
        <a-form-item label="学生" name="studentId" v-if="!isEdit">
          <a-select v-model:value="formState.studentId" placeholder="请选择学生" show-search
            :filter-option="filterStudentOption">
            <a-select-option v-for="student in students" :key="student.id" :value="student.id">
              {{ student.name }} - {{ student.className }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="档案类型" name="recordType" v-if="!isEdit">
          <a-radio-group v-model:value="formState.recordType">
            <a-radio value="STUDENT">
              <UserOutlined class="radio-icon" /> 个人档案
            </a-radio>
            <a-radio value="CLASS">
              <TeamOutlined class="radio-icon" /> 班级档案
            </a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item label="标题" name="title">
          <a-input v-model:value="formState.title" placeholder="请输入档案标题" />
        </a-form-item>
        <a-form-item label="记录日期" name="recordDate">
          <a-date-picker v-model:value="formState.recordDateValue" style="width: 100%;" value-format="YYYY-MM-DD" />
        </a-form-item>
        <a-form-item label="内容" name="content">
          <a-textarea v-model:value="formState.content" placeholder="请输入档案内容" :rows="4" />
        </a-form-item>
        <a-form-item label="图片">
          <a-upload v-model:file-list="fileList" :custom-request="handleCustomUpload" list-type="picture-card"
            :max-count="9" accept="image/*" @change="handleUploadChange">
            <div v-if="fileList.length < 9">
              <PlusOutlined />
              <div style="margin-top: 8px">上传</div>
            </div>
          </a-upload>
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- 查看档案详情弹窗 -->
    <a-modal v-model:open="detailModalVisible" width="700px" :footer="null">
      <template #title>
        <span class="modal-title">
          <CameraOutlined class="modal-title-icon" />
          {{ currentRecord?.title }}
        </span>
      </template>
      <div class="detail-content" v-if="currentRecord">
        <div class="detail-header">
          <div class="student-info">
            <div class="student-avatar">
              {{ currentRecord.student?.name?.charAt(0) || '班' }}
            </div>
            <div class="student-details">
              <div class="student-name">{{ currentRecord.student?.name || '班级档案' }}</div>
              <div class="student-class">{{ currentRecord.class?.name }}</div>
            </div>
          </div>
          <div class="record-date">
            <CalendarOutlined class="date-icon" />
            {{ formatDate(currentRecord.recordDate) }}
          </div>
        </div>

        <div class="detail-body">
          <p class="content-text">{{ currentRecord.content }}</p>

          <div v-if="currentRecord.images?.length" class="image-gallery">
            <a-image-preview-group>
              <a-image v-for="(img, index) in currentRecord.images" :key="index" :src="getImageUrl(img)"
                style="width: 100px; height: 100px; object-fit: cover; margin-right: 8px; border-radius: 8px;" />
            </a-image-preview-group>
          </div>
        </div>
      </div>
    </a-modal>

    <!-- 分页 -->
    <div class="pagination-wrapper" v-if="records.length > 0">
      <a-pagination v-model:current="pagination.current" v-model:pageSize="pagination.pageSize"
        :total="pagination.total" :show-size-changer="true" :show-total="(total: number) => `共 ${total} 条`"
        @change="handlePageChange" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import {
  PlusOutlined,
  CameraOutlined,
  UserOutlined,
  TeamOutlined,
  HomeOutlined,
  CalendarOutlined,
  EyeOutlined,
  EditOutlined,
  DeleteOutlined,
  FileTextOutlined,
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import {
  getTeacherGrowthRecords,
  createTeacherGrowthRecord,
  updateTeacherGrowthRecord,
  deleteTeacherGrowthRecord,
  type GrowthRecord,
  type CreateGrowthRecordDto,
  type UpdateGrowthRecordDto,
} from '@/api/growth';
import { trimFormModel } from '@/utils/trimFormModel';

// 图片加载状态管理
const recordLoadingStates = ref<Record<number, boolean>>({});
const recordImageLoaded = ref<Record<number, boolean>>({});
const recordImageError = ref<Record<number, boolean>>({});

// 监听 records 变化，初始化加载状态
const handleFilter = () => {
  recordLoadingStates.value = {};
  recordImageLoaded.value = {};
  recordImageError.value = {};
  pagination.current = 1;
  loadRecords();
};

const handleImageLoad = (recordId: number) => {
  recordLoadingStates.value[recordId] = false;
  recordImageLoaded.value[recordId] = true;
  recordImageError.value[recordId] = false;
};

const handleImageError = (recordId: number) => {
  recordLoadingStates.value[recordId] = false;
  recordImageLoaded.value[recordId] = false;
  recordImageError.value[recordId] = true;
};

import { getTeacherClasses, getTeacherStudents } from '@/api/teacher';
import { fileApi, validateFileType } from '@/api/file';

const loading = ref(false);
const submitting = ref(false);
const modalVisible = ref(false);
const detailModalVisible = ref(false);
const isEdit = ref(false);
const editId = ref<number | null>(null);
const formRef = ref<FormInstance>();

const filters = reactive({
  classId: undefined as number | undefined,
  keyword: '',
});

const pagination = reactive({
  current: 1,
  pageSize: 12,
  total: 0,
});

const myClasses = ref<any[]>([]);
const students = ref<any[]>([]);
const records = ref<GrowthRecord[]>([]);
const currentRecord = ref<GrowthRecord | null>(null);
const fileList = ref<any[]>([]);

const formState = reactive<CreateGrowthRecordDto & { recordDateValue?: string }>({
  studentId: undefined as any,
  classId: undefined,
  recordType: 'STUDENT',
  title: '',
  recordDateValue: '',
  recordDate: '',
  content: '',
  images: [],
});

const rules: Record<string, any[]> = {
  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  recordDateValue: [{ required: true, message: '请选择日期', trigger: 'change' }],
  content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
};

const getImageUrl = (path: string) => path;
const formatDate = (date: string) => date || '-';

const filterStudentOption = (input: string, option: any) => {
  return option.children[0].children.toLowerCase().includes(input.toLowerCase());
};

// 加载数据
const loadRecords = async () => {
  loading.value = true;
  try {
    const res = await getTeacherGrowthRecords({
      pageNum: pagination.current,
      pageSize: pagination.pageSize,
      classId: filters.classId,
      keyword: filters.keyword || undefined,
    });
    records.value = res.list || [];
    pagination.total = Number(res.total) || 0;
  } catch (error) {
    message.error('加载档案失败');
  } finally {
    loading.value = false;
  }
};

const loadClasses = async () => {
  try {
    myClasses.value = await getTeacherClasses();
  } catch (error) {
    console.error('加载班级失败', error);
  }
};

const loadStudents = async () => {
  try {
    const res = await getTeacherStudents({ pageNum: 1, pageSize: 500 });
    students.value = (res.list || []).map((s: any) => ({
      id: s.id,
      name: s.name,
      className: s.class?.name || '-',
      classId: s.classId,
    }));
  } catch (error) {
    console.error('加载学生失败', error);
  }
};

const handlePageChange = (page: number, pageSize: number) => {
  pagination.current = page;
  pagination.pageSize = pageSize;
  loadRecords();
};

const showAddModal = () => {
  isEdit.value = false;
  editId.value = null;
  formState.studentId = undefined as any;
  formState.classId = undefined;
  formState.recordType = 'STUDENT';
  formState.title = '';
  formState.recordDateValue = '';
  formState.recordDate = '';
  formState.content = '';
  formState.images = [];
  fileList.value = [];
  modalVisible.value = true;
};

const handleView = (record: GrowthRecord) => {
  currentRecord.value = record;
  detailModalVisible.value = true;
};

const handleEdit = (record: GrowthRecord) => {
  isEdit.value = true;
  editId.value = record.id;
  formState.title = record.title;
  formState.recordDateValue = record.recordDate;
  formState.recordDate = record.recordDate;
  formState.content = record.content || '';
  formState.images = record.images || [];
  fileList.value = record.images?.map((img: string, index: number) => ({
    uid: `-${index}`,
    name: img,
    status: 'done',
    url: img,
    response: { url: img },
  })) || [];
  modalVisible.value = true;
};

const handleDelete = async (id: number) => {
  try {
    await deleteTeacherGrowthRecord(id);
    message.success('删除成功');
    loadRecords();
  } catch (error) {
    message.error('删除失败');
  }
};

const handleModalOk = async () => {
  try {
    // 提交前移除字符串字段首尾空格，避免空格导致的误校验
    trimFormModel(formState as any);
    await formRef.value?.validate();
    submitting.value = true;

    // 根据选择的学生获取班级ID
    const selectedStudent = students.value.find(s => s.id === formState.studentId);
    const classId = formState.recordType === 'STUDENT' ? selectedStudent?.classId : filters.classId;

    if (isEdit.value && editId.value) {
      const updateData: UpdateGrowthRecordDto = {
        title: formState.title,
        recordDate: formState.recordDateValue,
        content: formState.content,
        images: formState.images,
      };
      await updateTeacherGrowthRecord(editId.value, updateData);
      message.success('更新成功');
    } else {
      const createData: CreateGrowthRecordDto = {
        studentId: formState.studentId,
        classId: classId,
        recordType: formState.recordType,
        title: formState.title,
        recordDate: formState.recordDateValue!,
        content: formState.content,
        images: formState.images,
      };
      await createTeacherGrowthRecord(createData);
      message.success('添加成功');
    }
    modalVisible.value = false;
    loadRecords();
  } catch (error) {
    message.error(isEdit.value ? '更新失败' : '添加失败');
  } finally {
    submitting.value = false;
  }
};

/** OSS 直传：自定义上传 */
const handleCustomUpload = async (options: any) => {
  const { file, onSuccess, onError, onProgress } = options;
  const uploadFile = file instanceof File ? file : (file?.originFileObj ?? file);

  const isImage = uploadFile.type?.startsWith('image/');
  if (!isImage) {
    message.error('只能上传图片文件');
    onError?.(new Error('只能上传图片'));
    return;
  }

  const validation = validateFileType(uploadFile, 'POSTER');
  if (!validation.valid) {
    message.error(validation.error);
    onError?.(new Error(validation.error));
    return;
  }

  try {
    const result = await fileApi.uploadFile(uploadFile, 'resource', {
      onProgress: (percent) => onProgress?.({ percent }),
    });
    onSuccess?.({ url: result.filePath });
  } catch (err: any) {
    const msg = err?.message || '上传失败';
    message.error(msg);
    onError?.(new Error(msg));
  }
};

const handleUploadChange = (info: any) => {
  formState.images = (info.fileList || [])
    .filter((f: any) => f.response?.url)
    .map((f: any) => f.response.url);
};

onMounted(() => {
  loadClasses();
  loadStudents();
  loadRecords();
});
</script>

<style scoped>
.growth-record-view {
  min-height: 100vh;
  background: linear-gradient(180deg, #FFF8F0 0%, #FFFFFF 100%);
  padding: 0;
}

.page-header {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  border-radius: 20px;
  padding: 24px 32px;
  margin-bottom: 24px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.header-title {
  display: flex;
  align-items: center;
  gap: 16px;
}

.title-icon-wrapper {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
}

.title-icon {
  font-size: 28px;
  color: white;
}

.title-text h2 {
  color: white;
  font-size: 24px;
  font-weight: 700;
  margin: 0;
}

.title-text p {
  color: rgba(255, 255, 255, 0.8);
  font-size: 14px;
  margin: 4px 0 0 0;
}

.header-stats {
  display: flex;
  gap: 32px;
}

.stat-item {
  text-align: center;
}

.stat-value {
  display: block;
  font-size: 32px;
  font-weight: 700;
  color: white;
}

.stat-label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
}

.action-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  padding: 16px 20px;
  background: white;
  border-radius: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.filters {
  display: flex;
  gap: 12px;
}

.add-btn {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  border: none;
  border-radius: 12px;
  height: 40px;
  padding: 0 24px;
  font-weight: 600;
}

.btn-icon {
  margin-right: 8px;
  font-size: 14px;
}

.record-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  margin-bottom: 24px;
}

.record-card {
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
}

.record-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}

.card-cover {
  position: relative;
  flex-shrink: 0;
  height: 160px;
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}

.cover-image {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);

  .image-wrapper {
    position: relative;
    width: 100%;
    height: 100%;

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .error-placeholder {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);

      .placeholder-icon {
        font-size: 48px;
        color: rgba(255, 255, 255, 0.8);
      }
    }
  }
}

.cover-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.image-count {
  position: absolute;
  bottom: 8px;
  right: 8px;
  z-index: 2;
  background: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 4px 8px;
  border-radius: 8px;
  font-size: 12px;
}

.cover-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}

.placeholder-icon {
  font-size: 48px;
  color: rgba(255, 255, 255, 0.8);
}

.type-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  padding: 4px 12px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 4px;
}

.badge-icon {
  font-size: 12px;
}

.type-badge.personal {
  background: #E3F2FD;
  color: #1976D2;
}

.type-badge.class {
  background: #FCE4EC;
  color: #E91E63;
}

.card-body {
  flex: 1;
  min-height: 0;
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.record-title {
  font-size: 16px;
  font-weight: 600;
  color: #2D3436;
  margin: 0 0 12px 0;
}

.record-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 12px;
}

.meta-item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #636E72;
}

.meta-icon {
  font-size: 12px;
  color: #f5576c;
}

.record-content {
  font-size: 13px;
  color: #636E72;
  line-height: 1.6;
  margin: 0 0 12px 0;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.card-actions {
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid #F0F0F0;
  background: #FAFAFA;
  margin-top: auto;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
  background: white;
  border-radius: 16px;
}

.empty-icon-wrapper {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
}

.empty-icon {
  font-size: 40px;
  color: white;
}

.empty-state p {
  color: #636E72;
  font-size: 16px;
  margin-bottom: 24px;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
}

.pagination-wrapper {
  display: flex;
  justify-content: center;
  padding: 24px;
  background: white;
  border-radius: 16px;
}

.detail-content {
  padding: 0;
}

.detail-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  border-radius: 16px;
  margin-bottom: 20px;
}

.student-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.student-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 600;
  color: #f5576c;
}

.student-name {
  color: white;
  font-size: 16px;
  font-weight: 600;
}

.student-class {
  color: rgba(255, 255, 255, 0.8);
  font-size: 12px;
}

.record-date {
  display: flex;
  align-items: center;
  gap: 8px;
  color: white;
  font-size: 14px;
}

.date-icon {
  font-size: 16px;
}

.detail-body {
  padding: 0;
}

.content-text {
  font-size: 14px;
  line-height: 1.8;
  color: #2D3436;
  margin-bottom: 20px;
}

.image-gallery {
  padding: 16px;
  background: #F8F9FA;
  border-radius: 12px;
}

.modal-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

.modal-title-icon {
  color: #f5576c;
  font-size: 18px;
}

.radio-icon {
  margin-right: 4px;
  color: #f5576c;
}

@media (max-width: 768px) {
  .header-content {
    flex-direction: column;
    gap: 16px;
    text-align: center;
  }

  .action-bar {
    flex-direction: column;
    gap: 12px;
  }

  .filters {
    width: 100%;
    flex-wrap: wrap;
  }

  .record-grid {
    grid-template-columns: 1fr;
  }
}
</style>
