const { useState, useEffect } = React;

const ReportMaster = () => {
  const [exams, setExams] = useState([]);
  const [departments, setDepartments] = useState([]);
  const [courses, setCourses] = useState([]);
  const [batches, setBatches] = useState([]);
  const [students, setStudents] = useState([]);

  const [selectedExam, setSelectedExam] = useState('');
  const [selectedDept, setSelectedDept] = useState('');
  const [selectedSem, setSelectedSem] = useState('');
  const [selectedCourse, setSelectedCourse] = useState('');
  const [selectedFormat, setSelectedFormat] = useState('');

  const [loading, setLoading] = useState(false);
  const [availableReports, setAvailableReports] = useState([]);

  useEffect(() => {
    Promise.all([
      fetch('/api/exams').then(r => r.json()),
      fetch('/api/courses').then(r => r.json()),
      fetch('/api/batches').then(r => r.json())
    ]).then(([examData, courseData, batchData]) => {
      setExams(examData);
      setCourses(courseData);
      setBatches(batchData);
      
      const depts = [];
      const deptMap = {};
      courseData.forEach(c => {
         if (c.Department && !deptMap[c.dept_id]) {
            deptMap[c.dept_id] = true;
            depts.push(c.Department);
         }
      });
      setDepartments(depts);
      if (examData.length > 0) setSelectedExam(examData[0].id);
    });
  }, []);

  const handleGenerateList = async () => {
    if (!selectedExam) return alert("Term is required");
    setLoading(true);

    const examObj = exams.find(e => String(e.id) === String(selectedExam));
    const isSummer = examObj?.season === 'Summer';

    let filteredCourses = courses.filter(c => {
      let match = true;
      if (selectedDept && String(c.dept_id) !== String(selectedDept)) match = false;
      if (selectedSem && String(c.semester) !== String(selectedSem)) match = false;
      if (selectedCourse && String(c.id) !== String(selectedCourse)) match = false;
      
      // Strict Season Check
      const isEven = parseInt(c.semester) % 2 === 0;
      if (isSummer && !isEven) match = false;
      if (!isSummer && isEven) match = false;
      
      return match;
    });

    const formatsToInclude = selectedFormat ? [selectedFormat] : ['K2-A', 'K2-B', 'K3', 'K4', 'K5', 'K6'];
    const reportsList = [];

    for (const c of filteredCourses) {
      for (const fmt of formatsToInclude) {
        const requiresBatch = ['K2-A', 'K2-B'].includes(fmt);

        if (requiresBatch) {
          for (const b of batches) {
            let hasData = false;
            try {
              if (fmt === 'K2-A') {
                const res = await fetch(`/api/lab-plans?exam_id=${selectedExam}&course_id=${c.id}&batch_id=${b.id}`);
                const data = await res.json();
                hasData = Array.isArray(data) && data.length > 0;
              } else if (fmt === 'K2-B') {
                const res = await fetch(`/api/tutorial-plans?exam_id=${selectedExam}&course_id=${c.id}&batch_id=${b.id}`);
                const data = await res.json();
                hasData = Array.isArray(data) && data.length > 0;
              }
            } catch(e) {}
            if (hasData) {
              reportsList.push({ id: `${fmt}_${c.id}_${b.id}`, format: fmt, course: c, batch: b, exam: examObj });
            }
          }
        } else {
          let hasData = false;
          try {
            if (fmt === 'K3') {
              const res = await fetch(`/api/lab-assessments?exam_id=${selectedExam}&course_id=${c.id}`);
              const data = await res.json();
              hasData = Array.isArray(data) && data.length > 0;
            } else if (fmt === 'K4') {
              const res = await fetch(`/api/k4-assessments?exam_id=${selectedExam}&course_id=${c.id}`);
              const data = await res.json();
              hasData = Array.isArray(data) && data.length > 0;
            } else if (fmt === 'K5') {
              const res = await fetch(`/api/theory-assessments?exam_id=${selectedExam}&course_id=${c.id}`);
              const data = await res.json();
              hasData = Array.isArray(data) && data.length > 0;
            } else if (fmt === 'K6') {
              const res = await fetch(`/api/sla-assessments?exam_id=${selectedExam}&course_id=${c.id}`);
              const data = await res.json();
              hasData = Array.isArray(data) && data.length > 0;
            }
          } catch(e) {}
          if (hasData) {
            reportsList.push({ id: `${fmt}_${c.id}`, format: fmt, course: c, batch: null, exam: examObj });
          }
        }
      }
    }

    setAvailableReports(reportsList);
    setLoading(false);
  };

  // Helper: fetch students with seat numbers
  const fetchStudentsWithSeats = async (courseId, examId) => {
    const [studentsRes, rosterRes] = await Promise.all([
      fetch(`/api/courses/${courseId}/eligible-students?exam_id=${examId}&t=${Date.now()}`).then(r => r.json()),
      fetch(`/api/exams/${examId}/roster?t=${Date.now()}`).then(r => r.json())
    ]);
    return (Array.isArray(studentsRes) ? studentsRes : []).map(s => {
      const reg = (Array.isArray(rosterRes) ? rosterRes : []).find(r => r.student_id === s.id);
      return { ...s, seat_number: reg ? reg.seat_number : '', is_detained: reg ? reg.is_detained : 0 };
    });
  };

  // Helper: academic year
  const getAcYear = (exam) => exam.season === 'Winter' ? `${exam.year}-${String(Number(exam.year)+1).slice(-2)}` : `${Number(exam.year)-1}-${String(exam.year).slice(-2)}`;

  const downloadReportK2A = async (report) => {
     try {
       const res = await fetch(`/api/lab-plans?exam_id=${report.exam.id}&course_id=${report.course.id}&batch_id=${report.batch.id}`);
       const plans = await res.json();
       if(plans.length === 0) return alert("No Lab Plan data found for this combination");
       
       const wsData = [];
       wsData.push(['', '', '', '', '', '', 'CIAAN \u2013 2023']);
       wsData.push(['', '', '', '', '', '', 'K2-A (PRACT)']);
       wsData.push([]);
       wsData.push(['For AICTE Diploma Engineering Courses', '', '', '', '', '', 'wef - 2023-24']);
       wsData.push(['', '', 'Maharashtra State Board of Technical Education', '', '', '', '']);
       wsData.push(['', '', 'LABORATORY PRACTICAL PLANNING', '', '', '', '']);
       wsData.push([]);
       wsData.push(['Institute Name:', 'Government Polytechnic Vikramgad', '', '', 'Institute Code:', '1547', '']);
       const acYear = getAcYear(report.exam);
       wsData.push(['Academic Year:', acYear, '', '', '', '', '']);
       let progStr = 'Diploma in Engineering'; const dObj = departments.find(d => String(d.id) === String(report.course.dept_id)); if(dObj) progStr = `Diploma in ${dObj.name}`;
       wsData.push(['Programme:', progStr, 'Course: ' + report.course.name, '', '', 'Course Code:', report.course.code]);
       wsData.push(['Semester:', report.course.semester + 'K', '', '', '', 'Batch:', report.batch.batch_name]);
       wsData.push([]);
       wsData.push(['Sr. No.', 'LLO', 'Practical Title', 'Planned Date', 'Performance Date', 'Remarks', 'Related self-learning']);
       
       plans.forEach(p => {
          wsData.push([ p.practical_no || '', p.co_mapped || '', p.title || '', p.planned_date || '', p.actual_date || '', p.remarks || '', p.self_learning || '' ]);
       });
       
       wsData.push([]);
       wsData.push(['(Faculty shall add here list of additional practicals i.e. practicals not suggested in curriculum)', '', '', '', '', '', '']);
       wsData.push([]);
       wsData.push(['Signature of Faculty', '', '', '', '', '', 'Signature of HoD']);
       wsData.push(['Name:', '', '', '', '', '', 'Name:']);
       
       const ws = window.XLSX.utils.aoa_to_sheet(wsData);
       for (const key in ws) {
          if (key[0] === '!') continue;
          const cellAddress = window.XLSX.utils.decode_cell(key);
          ws[key].s = {
              alignment: { vertical: 'center', horizontal: (cellAddress.r >= 10 && cellAddress.c === 2) ? 'left' : 'center', wrapText: true },
              font: { name: 'Times New Roman', sz: 10, bold: cellAddress.r < 7 || cellAddress.r === 10 }
          };
          if (cellAddress.r >= 10 && cellAddress.r < wsData.length - 5) {
              ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
          }
       }
       ws['!merges'] = [ { s: {r:4, c:2}, e: {r:4, c: 5} }, { s: {r:5, c:2}, e: {r:5, c: 5} }, { s: {r:3, c:0}, e: {r:3, c: 2} } ];
       ws['!cols'] = [ {wch: 8}, {wch: 35}, {wch: 40}, {wch: 15}, {wch: 15}, {wch: 15}, {wch: 20} ];

       const wb = window.XLSX.utils.book_new();
       window.XLSX.utils.book_append_sheet(wb, ws, "K2-A");
       window.XLSX.writeFile(wb, `K2-A_${report.course.code}_${report.batch.batch_name}.xlsx`);
     } catch (e) { alert("Failed to fetch specific report"); console.log(e); }
  };

  const downloadReportK2B = async (report) => {
     try {
       const res = await fetch(`/api/tutorial-plans?exam_id=${report.exam.id}&course_id=${report.course.id}&batch_id=${report.batch.id}`);
       const plans = await res.json();
       if(plans.length === 0) return alert("No Tutorial Plan data found for this combination");
       
       const wsData = [];
       wsData.push(['', '', '', '', '', '', 'CIAAN \u2013 2023']);
       wsData.push(['', '', '', '', '', '', 'K2-B (TUT)']);
       wsData.push([]);
       wsData.push(['For AICTE Diploma Engineering Courses', '', '', '', '', '', 'wef - 2023-24']);
       wsData.push(['', '', 'Maharashtra State Board of Technical Education', '', '', '', '']);
       wsData.push(['', '', 'TUTORIAL PLANNING', '', '', '', '']);
       wsData.push([]);
       wsData.push(['Institute Name:', 'Government Polytechnic Vikramgad', '', '', 'Institute Code:', '1547', '']);
       const acYear = getAcYear(report.exam);
       wsData.push(['Academic Year:', acYear, '', '', '', '', '']);
       let progStr = 'Diploma in Engineering'; const dObj = departments.find(d => String(d.id) === String(report.course.dept_id)); if(dObj) progStr = `Diploma in ${dObj.name}`;
       wsData.push(['Programme:', progStr, 'Course: ' + report.course.name, '', '', 'Course Code:', report.course.code]);
       wsData.push(['Semester:', report.course.semester + 'K', '', '', '', 'Batch:', report.batch.batch_name]);
       wsData.push([]);
       wsData.push(['Sr. No.', 'LLO', 'Tutorial Title', 'Planned Date', 'Performance Date', 'Remarks', 'Related self-learning']);
       
       plans.forEach(p => {
          wsData.push([ p.tutorial_no || '', p.co_mapped || '', p.title || '', p.planned_date || '', p.actual_date || '', p.remarks || '', p.self_learning || '' ]);
       });
       
       wsData.push([]);
       wsData.push(['(Faculty shall add here list of additional tutorials i.e. tutorials not suggested in curriculum)', '', '', '', '', '', '']);
       wsData.push([]);
       wsData.push(['Signature of Faculty', '', '', '', '', '', 'Signature of HoD']);
       wsData.push(['Name:', '', '', '', '', '', 'Name:']);
       
       const ws = window.XLSX.utils.aoa_to_sheet(wsData);
       for (const key in ws) {
          if (key[0] === '!') continue;
          const cellAddress = window.XLSX.utils.decode_cell(key);
          ws[key].s = {
              alignment: { vertical: 'center', horizontal: (cellAddress.r >= 10 && cellAddress.c === 2) ? 'left' : 'center', wrapText: true },
              font: { name: 'Times New Roman', sz: 10, bold: cellAddress.r < 7 || cellAddress.r === 10 }
          };
          if (cellAddress.r >= 10 && cellAddress.r < wsData.length - 5) {
              ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
          }
       }
       ws['!merges'] = [ { s: {r:4, c:2}, e: {r:4, c: 5} }, { s: {r:5, c:2}, e: {r:5, c: 5} }, { s: {r:3, c:0}, e: {r:3, c: 2} } ];
       ws['!cols'] = [ {wch: 8}, {wch: 35}, {wch: 40}, {wch: 15}, {wch: 15}, {wch: 15}, {wch: 20} ];

       const wb = window.XLSX.utils.book_new();
       window.XLSX.utils.book_append_sheet(wb, ws, "K2-B");
       window.XLSX.writeFile(wb, `K2-B_${report.course.code}_${report.batch.batch_name}.xlsx`);
     } catch (e) { alert("Failed to fetch specific report"); console.log(e); }
  };

  // ========== K3: EXACT CIAAN 2023 FORMAT ==========
  const downloadReportK3 = async (report) => {
    try {
      const course = report.course;
      const exam = report.exam;
      const faMax = parseFloat(course.fa_pr_max) || 0;

      const [studentsRes, marksRes, plansRes] = await Promise.all([
        fetch(`/api/courses/${course.id}/eligible-students?exam_id=${exam.id}&t=${Date.now()}`).then(r => r.json()),
        fetch(`/api/lab-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json()),
        fetch(`/api/lab-plans?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.ok ? r.json() : [])
      ]);
      const studentList = await fetchStudentsWithSeats(course.id, exam.id);
      const allMarks = Array.isArray(marksRes) ? marksRes : [];
      // Deduplicate lab plans by practical_no (API returns all batches)
      const rawPlans = Array.isArray(plansRes) ? plansRes : [];
      const seenPrac = {};
      const labPlans = rawPlans.filter(p => { if (seenPrac[p.practical_no]) return false; seenPrac[p.practical_no] = true; return true; }).sort((a,b) => a.practical_no - b.practical_no);
      let maxPracNo = 0;
      labPlans.forEach(p => { if (p.practical_no > maxPracNo) maxPracNo = p.practical_no; });
      allMarks.forEach(m => { if (m.practical_no > maxPracNo) maxPracNo = m.practical_no; });
      const N = maxPracNo || labPlans.length || 12;
      const sessionMax = allMarks.length > 0 ? parseFloat(allMarks[0].session_max_marks) || parseFloat(course.fa_pr_max) || 25 : parseFloat(course.fa_pr_max) || 25;

      const createRow = () => new Array(4 + N + 3).fill('');

      const row0 = createRow(); row0[row0.length - 1] = "K3";
      const row1 = createRow(); row1[0] = "For AICTE Diploma Engineering Courses"; row1[row1.length - 2] = "wef - 2023-24";
      const row2 = createRow(); row2[5] = "Maharashtra State Board of Technical Education";
      const row3 = createRow(); row3[5] = "FORMATIVE ASSESSMENT OF PRACTICAL (FA-PR)";
      const row4 = createRow();
      const row5 = createRow(); row5[0] = "Institute Name:"; row5[1] = "Government Polytechnic Vikramgad"; row5[2] = "Institute Code: 1547"; row5[row5.length - 3] = `Exam: ${exam.season} ${exam.year}`;
      const acYear = getAcYear(exam);
      const row6 = createRow(); row6[0] = "Academic Year:"; row6[1] = acYear;
      const row7 = createRow(); row7[0] = "Programme:"; row7[1] = "___________________________"; row7[5 > N? 4:5] = "Course:"; row7[6 > N? 5:6] = course.name; row7[9 > N? Math.min(8, N+1): 9] = "Course Code:"; row7[10 > N? Math.min(9, N+2): 10] = course.code;
      const row8 = createRow(); row8[0] = "Semester:"; row8[1] = String(course.semester) + 'K';
      const row9 = createRow();

      const row10 = createRow();
      row10[0] = "Roll\nNo."; row10[1] = "Enrollment\nNo."; row10[2] = "Exam Seat\nNumber"; row10[3] = "Name of the Student";
      row10[4] = `Practical / Tutorial\n(Marks out of ${sessionMax} per Experiment)`;
      row10[4+N] = `Total Marks\n(${sessionMax} x ${N} Expt.)`;
      row10[5+N] = `FA Marks of Practical Converted according to L-A Scheme (Max Marks: ${faMax})\n(Average across ${N} practicals, rounded up to full integer)`;
      row10[6+N] = "Signature of Student";

      const row11 = createRow();
      row11[0] = "1"; row11[1] = "2"; row11[2] = "3"; row11[3] = "4"; row11[4] = "5";
      row11[4+N] = "6"; row11[5+N] = "7"; row11[6+N] = "8";

      const row12 = createRow();
      for (let i = 0; i < N; i++) row12[4+i] = String(i+1);

      const row13 = createRow();
      row13[0] = "Related\nCO";
      for (let i = 0; i < N; i++) {
          let coVals = labPlans[i]?.related_co;
          if(coVals && String(coVals).trim() !== '') {
              let formatted = String(coVals).split(',').map(s => {
                  let sTrim = s.trim();
                  if(sTrim === '') return '';
                  return sTrim.toLowerCase().startsWith('co') ? sTrim.toUpperCase() : 'CO' + sTrim.toUpperCase();
              }).filter(Boolean).join(', ');
              row13[4+i] = formatted;
          }
      }

      const wsData = [row0, row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12, row13];

      studentList.forEach(s => {
        const srow = createRow();
        srow[0] = s.roll_no || '-'; srow[1] = s.enrollment_no; srow[2] = s.seat_number || '-'; srow[3] = s.full_name || s.name;
        let studentSum = 0, assessedCount = 0;
        for (let i = 0; i < N; i++) {
          const pNo = labPlans[i] ? labPlans[i].practical_no : i + 1;
          const prRecord = allMarks.find(m => m.student_id === s.id && String(m.practical_no) === String(pNo));
          if (prRecord) {
            const prMark = (parseFloat(prRecord.process_marks) || 0) + (parseFloat(prRecord.product_marks) || 0);
            srow[4 + i] = prMark; studentSum += prMark; assessedCount++;
          } else { srow[4 + i] = '-'; }
        }
        if (studentSum > 0 && assessedCount > 0) {
          srow[4 + N] = studentSum;
          const scaleFactor = faMax / (sessionMax * assessedCount);
          srow[5 + N] = Math.ceil(studentSum * scaleFactor);
        } else { srow[4 + N] = '-'; srow[5 + N] = '-'; }
        srow[6 + N] = '';
        wsData.push(srow);
      });

      wsData.push([], [], ["Signature of Faculty", "", "", "", "", "", "", "", "", "", "", "", "", "", "Signature of HoD"]);
      wsData.push(["Name", "", "", "", "", "", "", "", "", "", "", "", "", "", "Name"]);
      wsData.push([]);
      wsData.push(["Note: 1. Fractional marks shall be rounded to next full number"]);
      wsData.push(["      2. Faculty shall add more columns as per requirement"]);

      const ws = window.XLSX.utils.aoa_to_sheet(wsData);
      for (const key in ws) {
        if (key[0] === '!') continue;
        const cellAddress = window.XLSX.utils.decode_cell(key);
        ws[key].s = {
          alignment: { 
            wrapText: (cellAddress.r >= 10 && cellAddress.r !== wsData.length - 5) || cellAddress.r === 1,
            vertical: 'center', 
            horizontal: (cellAddress.r >= 10 && cellAddress.c === 3) ? 'left' : (cellAddress.r < 10 && cellAddress.c === 0 ? 'left' : 'center')
          },
          font: { name: 'Calibri', sz: cellAddress.r >= 10 ? 10 : 11, bold: cellAddress.r < 13 }
        };
        if (cellAddress.r >= 10 && cellAddress.r < wsData.length - 5) {
          ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
        }
      }
      ws['!merges'] = [
        { s: {r:2, c:5}, e: {r:2, c: Math.max(5, 4+N-1)} },
        { s: {r:3, c:5}, e: {r:3, c: Math.max(5, 4+N-1)} },
        { s: {r:10, c:0}, e: {r:11, c:0} }, { s: {r:10, c:1}, e: {r:11, c:1} },
        { s: {r:10, c:2}, e: {r:11, c:2} }, { s: {r:10, c:3}, e: {r:11, c:3} },
        { s: {r:10, c:4}, e: {r:10, c: 4+N-1} }, { s: {r:11, c:4}, e: {r:11, c: 4+N-1} },
        { s: {r:10, c:4+N}, e: {r:12, c:4+N} }, { s: {r:10, c:5+N}, e: {r:12, c:5+N} },
        { s: {r:10, c:6+N}, e: {r:12, c:6+N} }, { s: {r:13, c:0}, e: {r:13, c:3} }
      ];
      const widthsConfig = [{wch: 8}, {wch: 22}, {wch: 18}, {wch: 35}];
      for (let i = 0; i < N; i++) widthsConfig.push({wch: 4});
      widthsConfig.push({wch: 12}, {wch: 25}, {wch: 18});
      ws['!cols'] = widthsConfig;

      const wb = window.XLSX.utils.book_new();
      window.XLSX.utils.book_append_sheet(wb, ws, `Format_K3_FA_PR`);
      window.XLSX.writeFile(wb, `K3_FA_PR_Sheet_${course.code}.xlsx`);
    } catch (e) { alert("Failed to generate K3 report"); console.error(e); }
  };

  // ========== K4: EXACT CIAAN 2023 FORMAT ==========
  const downloadReportK4 = async (report) => {
    try {
      const course = report.course;
      const exam = report.exam;
      const studentList = await fetchStudentsWithSeats(course.id, exam.id);
      const marksRes = await fetch(`/api/k4-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json());
      const allMarks = Array.isArray(marksRes) ? marksRes : [];

      const wsData = [];
      wsData.push(['', '', '', '', 'CIAAN \u2013 2023']);
      wsData.push(['', '', '', '', 'K4']);
      wsData.push(['For AICTE Diploma Engineering Courses', '', '', '', 'wef - 2023-24']);
      wsData.push(['', 'Maharashtra State Board of Technical Education', '', '', '']);
      wsData.push(['', 'SUMMATIVE ASSESSMENT OF PRACTICAL (SA-PR)', '', '', '']);
      wsData.push([]);
      wsData.push(['Institute Name:', 'Government Polytechnic Vikramgad', '', 'Institute Code:', '1547']);
      const acYear = getAcYear(exam);
      wsData.push(['Academic Year:', acYear, '', 'Exam: Winter / Summer...................', '']);
      wsData.push(['Programme:', '', 'Course:', course.name, 'Course Code: ' + course.code]);

      const mMax = parseFloat(course.sa_pr_max) || 0;
      wsData.push(['Semester:', course.semester + 'K', `Marks Max: ${mMax}`, `Marks Minimum: ${Math.ceil(mMax * 0.4)}`, 'Date of Examination:']);
      wsData.push([]);
      wsData.push(['Sr. No.', 'Enrollment No.', 'Exam Seat Number', 'Name of the Student', `Marks obtained in SA part of Practical as per L-A Scheme (Max Marks ${mMax})`]);

      studentList.forEach((s, index) => {
        const mk = allMarks.find(m => m.student_id === s.id);
        wsData.push([index + 1, s.enrollment_no || '', s.seat_number || '', s.full_name || s.name, mk ? mk.marks_obtained : '']);
      });

      wsData.push([]);
      wsData.push(['Signature of Faculty', '', '', '', 'Signature of External Examiner']);
      wsData.push(['Name', '', '', '', 'Name']);
      wsData.push([]);
      wsData.push(['Note: 1. Fractional marks shall be rounded to next full number']); // K4
      wsData.push(['', '', '', '', 'Designation:']);
      wsData.push(['', '', '', '', 'Institute Code:']);
      wsData.push(['', '', '', '', 'Mobile No.:']);

      const ws = window.XLSX.utils.aoa_to_sheet(wsData);
      for (const key in ws) {
        if (key[0] === '!') continue;
        const cellAddress = window.XLSX.utils.decode_cell(key);
        ws[key].s = {
          alignment: { vertical: 'center', horizontal: 'center', wrapText: cellAddress.r >= 11 },
          font: { name: 'Times New Roman', sz: cellAddress.r >= 11 ? 11 : 12, bold: cellAddress.r < 5 || cellAddress.r === 11 }
        };
        if (cellAddress.r >= 11 && cellAddress.r < wsData.length - 6) {
          ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
        }
      }
      ws['!merges'] = [
        { s: {r:3, c:1}, e: {r:3, c: 4} },
        { s: {r:4, c:1}, e: {r:4, c: 4} },
      ];
      ws['!cols'] = [{wch: 8}, {wch: 15}, {wch: 18}, {wch: 35}, {wch: 25}];

      const wb = window.XLSX.utils.book_new();
      window.XLSX.utils.book_append_sheet(wb, ws, "K4 SA-PR");
      window.XLSX.writeFile(wb, `K4_${course.code}.xlsx`);
    } catch (e) { alert("Failed to generate K4 report"); console.error(e); }
  };

  // ========== K5: EXACT CIAAN 2023 FORMAT ==========
  const downloadReportK5 = async (report) => {
    try {
      const course = report.course;
      const exam = report.exam;
      const faThMax = parseFloat(course.fa_th_max) || 0;
      const studentList = await fetchStudentsWithSeats(course.id, exam.id);
      const marksRes = await fetch(`/api/theory-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json());
      const allMarks = Array.isArray(marksRes) ? marksRes : [];

      const createRow = () => new Array(9).fill('');

      const row0 = createRow(); row0[row0.length - 1] = "CIAAN - 2023";
      const row1 = createRow(); row1[row1.length - 1] = "K5";
      const row2 = createRow(); row2[0] = "For AICTE Diploma Engineering Course"; row2[row2.length - 1] = "wef - 2023-24";
      const row3 = createRow(); row3[4] = "Maharashtra State Board of Technical Education";
      const row4 = createRow(); row4[4] = "FORMATIVE ASSESSMENT OF THEORY (FA-TH)";
      const row5 = createRow();
      const row6 = createRow(); row6[0] = "Institute Name:"; row6[1] = "Government Polytechnic Vikramgad"; row6[2] = "Institute Code: 1547";
      const acYear = getAcYear(exam);
      const row7 = createRow(); row7[0] = "Academic Year"; row7[1] = acYear; row7[7] = "Exam:"; row7[8] = `${exam.season} ${exam.year}`;
      const row8 = createRow(); row8[0] = "Summer / Winter .............";
      const row9 = createRow();
      const row10 = createRow(); row10[0] = "Programme:"; row10[2] = "___________________________"; row10[4] = "Course:"; row10[5] = course.name; row10[7] = "Course Code:"; row10[8] = course.code;
      const row11 = createRow(); row11[0] = "Semester:"; row11[1] = String(course.semester) + 'K';
      const row12 = createRow();

      const row13 = createRow();
      row13[0] = "Roll\nNo."; row13[1] = "Enrollment\nNo."; row13[2] = "Exam Seat\nNumber"; row13[3] = "Name of the Student";
      row13[4] = `Marks of\nClass Test-1\n(Out of ${faThMax})`;
      row13[5] = `Marks of\nClass Test-2\n(Out of ${faThMax})`;
      row13[6] = "Average\nof 5\n& 6";
      row13[7] = `FA marks of\nTheory\nout of ${faThMax}`;
      row13[8] = "Signature\nof\nStudent";

      const row14 = createRow();
      row14[0] = "1"; row14[1] = "2"; row14[2] = "3"; row14[3] = "4"; row14[4] = "5"; row14[5] = "6"; row14[6] = "7"; row14[7] = "8"; row14[8] = "";

      const wsData = [row0, row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12, row13, row14];

      studentList.forEach(s => {
        const srow = createRow();
        srow[0] = s.roll_no || '-'; srow[1] = s.enrollment_no; srow[2] = s.seat_number || '-'; srow[3] = s.full_name || s.name;
        const sMarks = allMarks.filter(m => m.student_id === s.id);
        const ct1Rec = sMarks.find(m => String(m.test_type) === 'ct1' || String(m.test_no) === '1');
        const ct2Rec = sMarks.find(m => String(m.test_type) === 'ct2' || String(m.test_no) === '2');
        const ct1 = ct1Rec ? parseFloat(ct1Rec.marks_obtained) : null;
        const ct2 = ct2Rec ? parseFloat(ct2Rec.marks_obtained) : null;
        srow[4] = ct1 !== null ? ct1 : '-';
        srow[5] = ct2 !== null ? ct2 : '-';
        if (ct1 !== null || ct2 !== null) {
          let avg;
          if (ct1 !== null && ct2 !== null) avg = (ct1 + ct2) / 2;
          else avg = ct1 !== null ? ct1 : ct2;
          const rounded = Math.ceil(avg);
          srow[6] = rounded; srow[7] = rounded;
        } else { srow[6] = '-'; srow[7] = '-'; }
        srow[8] = '';
        wsData.push(srow);
      });

      wsData.push([]);
      wsData.push(["Signature of Faculty", "", "", "", "", "Signature of HoD"]);
      wsData.push(["Name", "", "", "", "", "Name"]);
      wsData.push([]);
      wsData.push(["Note: 1. Fractional marks shall be rounded to next full number"]); // K5

      const ws = window.XLSX.utils.aoa_to_sheet(wsData);
      for (const key in ws) {
        if (key[0] === '!') continue;
        const cellAddress = window.XLSX.utils.decode_cell(key);
        ws[key].s = {
          alignment: { 
            wrapText: cellAddress.r === 13,
            vertical: 'center', 
            horizontal: (cellAddress.r >= 13 && cellAddress.c === 3) ? 'left' : (cellAddress.r < 13 && cellAddress.c === 0 ? 'left' : 'center')
          },
          font: { 
            name: 'Times New Roman', 
            sz: cellAddress.r >= 13 ? 11 : 12, 
            bold: cellAddress.r === 3 || cellAddress.r === 4 || cellAddress.r === 14 
          }
        };
        if (cellAddress.r >= 13 && cellAddress.r < wsData.length - 3) {
          ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
        }
      }
      ws['!merges'] = [
        { s: {r:3, c:4}, e: {r:3, c: 5} },
        { s: {r:4, c:4}, e: {r:4, c: 5} },
        { s: {r:2, c:0}, e: {r:2, c: 3} }
      ];
      ws['!cols'] = [{wch: 8}, {wch: 15}, {wch: 15}, {wch: 35}, {wch: 12}, {wch: 12}, {wch: 10}, {wch: 12}, {wch: 15}];

      const wb = window.XLSX.utils.book_new();
      window.XLSX.utils.book_append_sheet(wb, ws, `Format_K5_FA_TH`);
      window.XLSX.writeFile(wb, `K5_FA_TH_Sheet_${course.code}.xlsx`);
    } catch (e) { alert("Failed to generate K5 report"); console.error(e); }
  };

  // ========== K6: EXACT CIAAN 2023 FORMAT ==========
  const downloadReportK6 = async (report) => {
    try {
      const course = report.course;
      const exam = report.exam;
      const subjectSlaMax = parseFloat(course.sla_max) || 0;
      const studentList = await fetchStudentsWithSeats(course.id, exam.id);

      const [marksRes, plansRes] = await Promise.all([
        fetch(`/api/sla-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json()),
        fetch(`/api/sla-plans?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.ok ? r.json() : [])
      ]);
      const allMarks = Array.isArray(marksRes) ? marksRes : [];
      const activities = Array.isArray(plansRes) ? plansRes : [];
      const totalMaxMarks = activities.reduce((sum, act) => sum + parseFloat(act.max_marks || 0), 0);

      const baseColsCount = 4;
      const endColsCount = 3;
      const totalCols = baseColsCount + activities.length + endColsCount;
      const createRow = () => new Array(totalCols).fill('');

      const headerRows = [];
      const r0 = createRow(); r0[r0.length - 1] = "CIAAN - 2023"; headerRows.push(r0);
      const r1 = createRow(); r1[r1.length - 1] = "K6"; headerRows.push(r1);
      const r2 = createRow(); r2[0] = "For AICTE Diploma Engineering Courses"; r2[r2.length - 1] = "wef - 2023-24"; headerRows.push(r2);

      const midPoint = Math.floor(totalCols / 2) - 1;
      const r3 = createRow(); r3[midPoint] = "Maharashtra State Board of Technical Education"; headerRows.push(r3);
      const r4 = createRow(); r4[midPoint] = "SELF LEARNING ASSESSMENT (SLA)"; headerRows.push(r4);
      const r5 = createRow(); r5[midPoint] = "Micro project / Assignment / Activities for specific learning / skills development"; headerRows.push(r5);
      const r6 = createRow(); headerRows.push(r6);

      const r7 = createRow(); r7[0] = "Institute Name:"; r7[1] = "Government Polytechnic Vikramgad"; r7[2] = "Institute Code: 1547"; headerRows.push(r7);
      const acYear = getAcYear(exam);
      const r8 = createRow(); r8[0] = "Academic Year"; r8[1] = acYear; r8[totalCols - 2] = "Exam:"; r8[totalCols - 1] = `${exam.season} ${exam.year}`; headerRows.push(r8);
      const r9 = createRow(); r9[0] = "Summer / Winter ............."; headerRows.push(r9);

      let progStr = 'Diploma in Engineering'; const dObj = departments.find(d => String(d.id) === String(course.dept_id)); if(dObj) progStr = `Diploma in ${dObj.name}`;
      const r10 = createRow(); r10[0]="Programme:"; r10[2]=progStr; r10[midPoint]="Course:"; r10[midPoint+1]=course.name; r10[totalCols-2]="Course Code:"; r10[totalCols-1]=course.code; headerRows.push(r10);
      const r11 = createRow(); r11[0] = "Semester:"; r11[1] = String(course.semester) + 'K'; headerRows.push(r11);
      const r12 = createRow(); headerRows.push(r12);

      const r13 = createRow();
      r13[0] = "Roll\nNo."; r13[1] = "Enrollment\nNo."; r13[2] = "Exam Seat\nNumber"; r13[3] = "Name of the Student";
      r13[totalCols - 3] = `Total\nMax Marks`;
      r13[totalCols - 2] = `SLA Marks\naccording to L-\nA Scheme\n(Max\nMarks ${subjectSlaMax})`;
      r13[totalCols - 1] = "Signature\nof\nStudent";
      headerRows.push(r13);

      const r14 = createRow();
      for(let i=0; i<4; i++) r14[i] = "";
      activities.forEach((act, i) => { r14[4 + i] = `${i+1}*\n[MAX: ${act.max_marks}]`; });
      headerRows.push(r14);

      const wsData = [...headerRows];

      studentList.forEach(s => {
        const srow = createRow();
        srow[0] = s.roll_no || '-'; srow[1] = s.enrollment_no; srow[2] = s.seat_number || '-'; srow[3] = s.full_name || s.name;
        let total = 0;
        activities.forEach((act, i) => {
          const mk = allMarks.find(m => m.student_id === s.id && String(m.activity_no) === String(act.activity_no));
          if (mk && mk.marks !== undefined && mk.marks !== null) {
            const v = parseFloat(mk.marks); srow[4 + i] = v; total += v;
          } else { srow[4 + i] = '-'; }
        });
        srow[totalCols - 3] = total > 0 ? total : '-';
        let converted = '-';
        if (total > 0 && totalMaxMarks > 0 && subjectSlaMax > 0) {
          converted = Math.ceil((total / totalMaxMarks) * subjectSlaMax);
        } else if (total > 0) {
          converted = Math.ceil(total);
        }
        srow[totalCols - 2] = converted;
        srow[totalCols - 1] = "";
        wsData.push(srow);
      });

      wsData.push([]);
      const footer = createRow(); footer[0] = "Signature of Faculty"; footer[totalCols-2] = "Signature of HoD"; wsData.push(footer);
      const footer2 = createRow(); footer2[0] = "Name"; footer2[totalCols-2] = "Name"; wsData.push(footer2);

      const ws = window.XLSX.utils.aoa_to_sheet(wsData);
      for (const key in ws) {
        if (key[0] === '!') continue;
        const cellAddress = window.XLSX.utils.decode_cell(key);
        ws[key].s = {
          alignment: { 
            wrapText: cellAddress.r >= 13,
            vertical: 'center', 
            horizontal: (cellAddress.r >= 13 && cellAddress.c === 3) ? 'left' : 'center'
          },
          font: { 
            name: 'Times New Roman', 
            sz: cellAddress.r >= 13 ? 11 : 12, 
            bold: cellAddress.r === 3 || cellAddress.r === 4 || cellAddress.r === 5 || cellAddress.r === 13 || cellAddress.r === 14
          }
        };
        if (cellAddress.r >= 13 && cellAddress.r < wsData.length - 3) {
          ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
        }
      }
      ws['!merges'] = [
        { s: {r:3, c:midPoint}, e: {r:3, c: midPoint+2} },
        { s: {r:4, c:midPoint}, e: {r:4, c: midPoint+2} },
        { s: {r:5, c:midPoint}, e: {r:5, c: midPoint+2} },
        { s: {r:13, c:4}, e: {r:13, c: 4 + activities.length - 1} },
        { s: {r:13, c:0}, e: {r:14, c:0} }, { s: {r:13, c:1}, e: {r:14, c:1} },
        { s: {r:13, c:2}, e: {r:14, c:2} }, { s: {r:13, c:3}, e: {r:14, c:3} },
        { s: {r:13, c:totalCols-3}, e: {r:14, c:totalCols-3} },
        { s: {r:13, c:totalCols-2}, e: {r:14, c:totalCols-2} },
        { s: {r:13, c:totalCols-1}, e: {r:14, c:totalCols-1} }
      ];
      const widthsConfig = [ {wch: 8}, {wch: 22}, {wch: 18}, {wch: 35} ];
      activities.forEach(() => widthsConfig.push({wch: 15}));
      widthsConfig.push({wch: 12}, {wch: 15}, {wch: 15});
      ws['!cols'] = widthsConfig;

      const wb = window.XLSX.utils.book_new();
      window.XLSX.utils.book_append_sheet(wb, ws, `Format_K6_SLA`);
      window.XLSX.writeFile(wb, `K6_SLA_Sheet_${course.code}.xlsx`);
    } catch (e) { alert("Failed to generate K6 report"); console.error(e); }
  };

  const handleDownloadAction = (report) => {
    if (report.format === 'K2-A') return downloadReportK2A(report);
    if (report.format === 'K2-B') return downloadReportK2B(report);
    if (report.format === 'K3') return downloadReportK3(report);
    if (report.format === 'K4') return downloadReportK4(report);
    if (report.format === 'K5') return downloadReportK5(report);
    if (report.format === 'K6') return downloadReportK6(report);
  };

  const handlePdfAction = async (report) => {
    try {
      const course = report.course;
      const exam = report.exam;
      const { jsPDF } = window.jspdf;
      const acYear = getAcYear(exam);
      const studentList = await fetchStudentsWithSeats(course.id, exam.id);

      const addHeader = (doc, contentLines) => {
        const pageW = doc.internal.pageSize.getWidth();
        const pageH = doc.internal.pageSize.getHeight();
        doc.setFont('times', 'bold');
        doc.setFontSize(10);
        doc.text('CIAAN – 2023', pageW - 15, 8, { align: 'right' });
        doc.text(contentLines.kFormat, pageW - 15, 12, { align: 'right' });
        
        doc.setLineWidth(0.5);
        doc.line(15, 14, pageW - 15, 14);

        doc.setFontSize(10);
        doc.text('For AICTE Diploma Engineering Courses', 15, 18);
        doc.text('wef - 2023-24', pageW - 15, 18, { align: 'right' });

        doc.setFontSize(11);
        doc.text('Maharashtra State Board of Technical Education', pageW / 2, 23, { align: 'center' });
        doc.setFontSize(10);
        doc.text(contentLines.title, pageW / 2, 28, { align: 'center' });
        if (contentLines.subtitle) {
          doc.setFontSize(10);
          doc.setFont('times', 'normal');
          doc.text(contentLines.subtitle, pageW / 2, 32, { align: 'center' });
        }

        const startY = contentLines.subtitle ? 38 : 34;
        doc.setFont('times', 'normal');
        doc.setFontSize(10);
        doc.text('Institute Name:', 15, startY);
        doc.text('Government Polytechnic Vikramgad', 42, startY);
        
        if (contentLines.instituteRight) {
          doc.text(contentLines.instituteRight, pageW / 2 + 15, startY);
        }
        doc.text('Academic Year:', 15, startY + 5);
        doc.text(String(acYear), 42, startY + 5);

        if (contentLines.examLineRight) {
           doc.text(contentLines.examLineRight, pageW - 15, startY + 5, { align: 'right' });
        } else {
           doc.text(`Exam: ${exam.season} ${exam.year}`, pageW - 15, startY + 5, { align: 'right' });
        }

        doc.text('Programme:', 15, startY + 10);
        const progName = contentLines.programme || 'Diploma in Engineering';
        doc.text(progName, 35, startY + 10);

        doc.text('Course:', 15, startY + 15);
        doc.text(course.name, 35, startY + 15);
        doc.text('Course Code:', pageW - 45, startY + 15);
        doc.text(course.code, pageW - 15, startY + 15, { align: 'right' });

        doc.text('Semester:', 15, startY + 20);
        doc.text(String(course.semester) + 'K', 42, startY + 20);
        
        let finalHeaderY = startY + 20;

        if (contentLines.semesterExtraData) {
           let cx = 80;
           contentLines.semesterExtraData.forEach((extra, idx) => {
              doc.text(extra, cx, startY + 20);
              cx += Math.max(30, extra.length * 2);
           });
        }
        
        return finalHeaderY + 5; 
      };

      const addFooter = (doc, tableFinalY, extraNotes = []) => {
         let startY = tableFinalY + 15;
         const pageW = doc.internal.pageSize.getWidth();
         doc.setFontSize(11);
         doc.setFont('times', 'normal');
         doc.text('Signature of Faculty', 15, startY);
         doc.text('Signature of HoD', pageW - 65, startY, { align: 'left' });
         doc.text('Name: ______________________', 15, startY + 8);
         doc.text('Name: ______________________', pageW - 65, startY + 8, { align: 'left' });
         
         if (extraNotes.length > 0) {
            startY += 20;
            doc.setFont('times', 'bold');
            doc.text('Note:', 15, startY);
            doc.setFont('times', 'normal');
            extraNotes.forEach((line, idx) => {
               doc.text(`${idx + 1}. ${line}`, 25, startY + (idx * 5));
            });
         }
      };

      if (report.format === 'K3') {
        const doc = new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a4' });
        const faMax = parseFloat(course.fa_pr_max) || 0;
        const [marksRes, plansRes] = await Promise.all([
          fetch(`/api/lab-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json()),
          fetch(`/api/lab-plans?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.ok ? r.json() : [])
        ]);
        const allMarks = Array.isArray(marksRes) ? marksRes : [];
        const rawPlans = Array.isArray(plansRes) ? plansRes : [];
        const seenP = {}; const labPlans = rawPlans.filter(p => { if (seenP[p.practical_no]) return false; seenP[p.practical_no]=true; return true; }).sort((a,b)=>a.practical_no-b.practical_no);
        let maxPN = 0; labPlans.forEach(p => { if(p.practical_no>maxPN) maxPN=p.practical_no; }); allMarks.forEach(m => { if(m.practical_no>maxPN) maxPN=m.practical_no; });
        let N = maxPN || labPlans.length || 12;
        if (course && String(course.code).trim() === '316004') {
            N = 8;
        }
        const sessionMax = allMarks.length > 0 ? parseFloat(allMarks[0].session_max_marks) || parseFloat(course.fa_pr_max) || 25 : parseFloat(course.fa_pr_max) || 25;

        const startY = addHeader(doc, { programme: `Diploma in ${departments.find(d => String(d.id) === String(course.dept_id))?.name || 'Engineering'}`, 
           kFormat: 'K3',
           title: 'FORMATIVE ASSESSMENT OF PRACTICAL (FA-PR)',
           instituteRight: 'Institute Code: 1547'
        });

        // The header strictly single lines Enrollment No, Exam Seat Number, Total Marks.
        // We use cellWidth: 'wrap' to ensure autoTable treats the cell as rigid.
        const head = [
          [
            { content: 'Roll\nNo.', rowSpan: 3 },
            { content: 'Enrollment\nNo.', rowSpan: 3 },
            { content: 'Exam Seat\nNumber', rowSpan: 3 },
            { content: 'Name of the Student', rowSpan: 3 },
            { content: `Practical Marks (Out of ${sessionMax})`, colSpan: N },
            { content: `Total\nMarks\n(${sessionMax} x ${N})`, rowSpan: 3 },
            { content: `FA Marks\n(Max ${faMax})`, rowSpan: 3 },
            { content: 'Signature\nof\nStudent', rowSpan: 3 }
          ],
          [
            ...Array.from({length: N}, (_, i) => ({ content: String(i+1), styles: { fillColor: [230,230,230] } }))
          ],
          [
            ...Array.from({length: N}, (_, i) => {
                 let coVals = labPlans[i]?.related_co;
                 let formatted = '';
                 if(coVals && String(coVals).trim() !== '') {
                     formatted = String(coVals).split(',').map(s => {
                         let sTrim = s.trim();
                         if(sTrim === '') return '';
                         return sTrim.toLowerCase().startsWith('co') ? sTrim.toUpperCase() : 'CO' + sTrim.toUpperCase();
                     }).filter(Boolean).join(', ');
                 }
                 return { content: formatted, styles: { fillColor: [240,240,240] } }
            })
          ]
        ];

        const body = studentList.map(s => {
          const row = [s.roll_no || '-', s.enrollment_no, s.seat_number || '-', s.full_name || s.name];
          let sum = 0, cnt = 0;
          for (let i = 0; i < N; i++) {
            const pNo = labPlans[i] ? labPlans[i].practical_no : i + 1;
            const mk = allMarks.find(m => m.student_id === s.id && String(m.practical_no) === String(pNo));
            if (mk) { const v = (parseFloat(mk.process_marks)||0)+(parseFloat(mk.product_marks)||0); row.push(v); sum+=v; cnt++; }
            else row.push('-');
          }
          if (sum > 0 && cnt > 0) { 
             row.push(sum); 
             row.push(Math.round((sum * faMax) / (sessionMax * cnt))); 
          } else { 
             row.push('-'); 
             row.push({ content: '401', styles: { fontStyle: 'bold', fontSize: 11 } }); 
          }
          row.push(''); // Signature

          if (s.is_detained) {
             const detainedRow = [s.roll_no || '-', s.enrollment_no, s.seat_number || '-', s.full_name || s.name];
             detainedRow.push({ content: 'DETAINED', colSpan: N + 1, styles: { halign: 'center', fontStyle: 'bold' } });
             detainedRow.push({ content: '402', styles: { fontStyle: 'bold', fontSize: 11 } });
             detainedRow.push('');
             return detainedRow;
          }
          return row;
        });

        doc.autoTable({ 
           head, 
           body, 
           startY, 
           theme: 'grid',
           rowPageBreak: 'avoid',
           styles: { font: 'times', fontSize: 9, textColor: [0,0,0], lineColor: [0,0,0], lineWidth: 0.1, halign: 'center', valign: 'middle', cellPadding: 0.5 }, 
           headStyles: { fillColor: [255,255,255], fontStyle: 'bold' }, 
           bodyStyles: { minCellHeight: 10 },
           columnStyles: { 
             0: { cellWidth: 10 }, // Roll No
             1: { cellWidth: 21 }, // Enrollment No
             2: { cellWidth: 14 }, // Exam Seat Number
             3: { halign: 'left', cellWidth: 35 }, // Name
             [4+N]: { cellWidth: 14 }, // Total Marks
             [4+N+1]: { cellWidth: 12, fontSize: 11 }, // FA Marks (removed fontStyle: bold)
             [4+N+2]: { cellWidth: 14 } // Signature
           }, 
           margin: { left: 10, right: 10 } 
        });
        
        addFooter(doc, doc.lastAutoTable.finalY + 10, ['Fractional marks shall be rounded to next full number']);
        doc.save(`K3_FA_PR_Sheet_${course.code}.pdf`);

      } else if (report.format === 'K4') {
        const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        const saMax = parseFloat(course.sa_pr_max) || 0;
        const marksRes = await fetch(`/api/k4-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json());
        const allMarks = Array.isArray(marksRes) ? marksRes : [];
        const startY = addHeader(doc, { programme: `Diploma in ${departments.find(d => String(d.id) === String(course.dept_id))?.name || 'Engineering'}`, 
           kFormat: 'K4',
           title: 'SUMMATIVE ASSESSMENT OF PRACTICAL (SA-PR)',
           instituteRight: 'Institute Code: 1547',
           semesterExtraData: [`Marks Max: ${saMax}`, `Marks Minimum: ${Math.ceil(saMax * 0.4)}`, 'Date of Examination:']
        });

        const head = [[
          { content: 'Sr.\nNo.', styles: { minCellWidth: 10, halign: 'center' } },
          { content: 'Enrollment\nNo.' }, 
          { content: 'Exam Seat\nNumber' }, 
          { content: 'Name of the Student', styles: { minCellWidth: 50 } }, 
          { content: `SA Marks\n(Max ${saMax})`, styles: { minCellWidth: 30 } }
        ]];

        const body = studentList.map((s, idx) => {
          const mk = allMarks.find(m => m.student_id === s.id);
          let val = mk ? String(mk.marks_obtained).trim().toUpperCase() : '';
          let finalMark = val;
          if (s.is_detained) {
             finalMark = { content: '402', styles: { fontStyle: 'bold', fontSize: 11 } };
          } else if (val === '0' || val === 'AB' || val === 'ABSENT' || val === '') {
             finalMark = { content: '401', styles: { fontStyle: 'bold', fontSize: 11 } };
          } else {
             finalMark = { content: val, styles: { fontSize: 11 } };
          }
          return [idx + 1, s.enrollment_no||'', s.seat_number||'-', s.full_name||s.name, finalMark];
        });

        doc.autoTable({ 
           head, body, 
           startY, theme: 'grid',
           rowPageBreak: 'avoid', 
           styles: { font: 'times', fontSize: 9, textColor: [0,0,0], lineColor: [0,0,0], lineWidth: 0.1, halign: 'center', valign: 'middle', cellPadding: 0.5 }, 
           headStyles: { fillColor: [255,255,255], fontStyle: 'bold' }, 
           bodyStyles: { minCellHeight: 10 },
           columnStyles: { 
              0: { cellWidth: 12 }, 
              1: { cellWidth: 25 }, 
              2: { cellWidth: 25 },
              3: { halign: 'left', cellWidth: 'auto' }, 
              4: { cellWidth: 20, fontSize: 11 }
           }, 
           margin: { left: 15, right: 15 } 
        });

        const finalY = doc.lastAutoTable.finalY + 15;
        const pageW = doc.internal.pageSize.getWidth();
        doc.text('Signature of Faculty', 15, finalY);
        doc.text('Signature of External Examiner', pageW - 65, finalY, { align: 'left' });
        doc.text('Name: ______________________', 15, finalY + 8);
        doc.text('Name: ______________________', pageW - 65, finalY + 8, { align: 'left' });
        doc.text('Designation:', pageW - 65, finalY + 16, { align: 'left' });
        doc.text('Institute Code:', pageW - 65, finalY + 24, { align: 'left' });
        doc.text('Mobile No.:', pageW - 65, finalY + 32, { align: 'left' });
        doc.text('Note: 1. Fractional marks shall be rounded to next full number', 15, finalY + 44);

        doc.save(`K4_${course.code}.pdf`);

      } else if (report.format === 'K5') {
        const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        const faThMax = parseFloat(course.fa_th_max) || 0;
        const marksRes = await fetch(`/api/theory-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json());
        const allMarks = Array.isArray(marksRes) ? marksRes : [];
        const startY = addHeader(doc, { programme: `Diploma in ${departments.find(d => String(d.id) === String(course.dept_id))?.name || 'Engineering'}`, 
           kFormat: 'K5',
           title: 'FORMATIVE ASSESSMENT OF THEORY (FA-TH)'
        });

        const head = [
           [
             { content: 'Roll\nNo.' },
             { content: 'Enrollment\nNo.' },
             { content: 'Exam Seat\nNumber' },
             { content: 'Name of the Student' },
             { content: `UT-1\n(${faThMax})` },
             { content: `UT-2\n(${faThMax})` },
             { content: 'Average' },
             { content: `FA\nMarks` },
             { content: 'Signature' }
           ]
        ];

        const body = studentList.map(s => {
          const sMarks = allMarks.filter(m => String(m.student_id) === String(s.id));
          const ct1Rec = sMarks.find(m => String(m.test_type).toLowerCase() === 'ct1' || String(m.test_no) === '1');
          const ct2Rec = sMarks.find(m => String(m.test_type).toLowerCase() === 'ct2' || String(m.test_no) === '2');
          
          const ct1Val = ct1Rec ? String(ct1Rec.marks_obtained).trim().toUpperCase() : '';
          const ct2Val = ct2Rec ? String(ct2Rec.marks_obtained).trim().toUpperCase() : '';
          
          // 0 treated as 0, AB treated as AB
          let ct1Disp = (ct1Val === 'AB' || ct1Val === 'ABSENT') ? 'AB' : (ct1Val === '' ? '-' : ct1Val);
          let ct2Disp = (ct2Val === 'AB' || ct2Val === 'ABSENT') ? 'AB' : (ct2Val === '' ? '-' : ct2Val);
          
          // AB counts as 0 for calculations
          let ct1Num = (ct1Disp === 'AB' || ct1Disp === '-') ? 0 : (parseFloat(ct1Disp) || 0);
          let ct2Num = (ct2Disp === 'AB' || ct2Disp === '-') ? 0 : (parseFloat(ct2Disp) || 0);
          
          // Calculate average (consider count of tests defined for the course, usually 2)
          // If only one test happened, average is just that test. If both, (T1+T2)/2.
          let rawAvg = 0;
          if (ct1Rec && ct2Rec) rawAvg = (ct1Num + ct2Num) / 2;
          else rawAvg = ct1Rec ? ct1Num : (ct2Rec ? ct2Num : 0);
          
          let avg = Math.ceil(rawAvg);
          
          // K5 Final Marks column: numeric average. No 401 code. 402 is bolded below.
          let finalFaObj = { content: String(avg), styles: { fontSize: 11 } };
          
          if (s.is_detained) {
             const detainedRow = [s.roll_no || '-', s.enrollment_no, s.seat_number || '-', s.full_name || s.name];
             detainedRow.push({ content: 'DETAINED', colSpan: 3, styles: { halign: 'center', fontStyle: 'bold' } });
             detainedRow.push({ content: '402', styles: { fontStyle: 'bold', fontSize: 11 } });
             detainedRow.push('');
             return detainedRow;
          }
          
          return [s.roll_no||'-', s.enrollment_no, s.seat_number||'-', s.full_name||s.name, ct1Disp, ct2Disp, String(avg), finalFaObj, ''];
        });

        doc.autoTable({ 
           head, body, 
           startY, theme: 'grid',
           rowPageBreak: 'avoid', 
           styles: { font: 'times', fontSize: 9, textColor: [0,0,0], lineColor: [0,0,0], lineWidth: 0.1, halign: 'center', valign: 'middle', cellPadding: 0.5 }, 
           headStyles: { fillColor: [255,255,255], fontStyle: 'bold' }, 
           bodyStyles: { minCellHeight: 10 },
           columnStyles: { 
             0: { cellWidth: 10 }, 
             1: { cellWidth: 21 }, 
             2: { cellWidth: 14 }, 
             3: { halign: 'left', cellWidth: 35 }, 
             7: { fontSize: 11, cellWidth: 12 } // removed fontStyle: bold
           }, 
           margin: { left: 10, right: 10 } 
        });

        addFooter(doc, doc.lastAutoTable.finalY + 10, ['Fractional marks shall be rounded to next full number']);
        doc.save(`K5_FA_TH_Sheet_${course.code}.pdf`);

      } else if (report.format === 'K6') {
        const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        const slaMax = parseFloat(course.sla_max) || 0;
        const [marksRes, plansRes] = await Promise.all([
          fetch(`/api/sla-assessments?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.json()),
          fetch(`/api/sla-plans?exam_id=${exam.id}&course_id=${course.id}&t=${Date.now()}`).then(r => r.ok ? r.json() : [])
        ]);
        const allMarks = Array.isArray(marksRes) ? marksRes : [];
        const activities = Array.isArray(plansRes) ? plansRes : [];
        const totalMaxMarks = activities.reduce((s, a) => s + parseFloat(a.max_marks||0), 0);

        let startY = addHeader(doc, { programme: `Diploma in ${departments.find(d => String(d.id) === String(course.dept_id))?.name || 'Engineering'}`, 
           kFormat: 'K6',
           title: 'SELF LEARNING ASSESSMENT (SLA)' // removed subtitle to save space
        });

        // 1. Legend Table for activities
        if (activities.length > 0) {
           doc.autoTable({
              startY,
              head: [['No.', 'Activity Name', 'Max Marks']],
              body: activities.map((a, i) => [
                 `${i + 1}`,
                 a.activity_name || 'Unnamed Activity',
                 a.max_marks || 0
              ]),
              theme: 'grid',
              styles: { font: 'times', fontSize: 9, halign: 'center' },
              columnStyles: {
                 1: { halign: 'left' }
              },
              margin: { left: 15, right: 15 }
           });
           startY = doc.lastAutoTable.finalY + 10;
        }

        const head = [
          [
             { content: 'Roll\nNo.', rowSpan: 2 },
             { content: 'Enrollment\nNo.', rowSpan: 2 },
             { content: 'Exam Seat\nNumber', rowSpan: 2 },
             { content: 'Name of the Student', rowSpan: 2 },
             { content: 'Micro project / SLA\nMarks Obtained', colSpan: activities.length },
             { content: `Max Marks\n(${totalMaxMarks})`, rowSpan: 2, styles: { minCellWidth: 15 } },
             { content: `SLA Marks\n(Max ${slaMax})`, rowSpan: 2 },
             { content: 'Signature', rowSpan: 2 }
          ],
          [
             ...activities.map((a, i) => ({ content: `${i+1}\n(${a.max_marks})` }))
          ]
        ];

        const body = studentList.map(s => {
          const row = [s.roll_no||'-', s.enrollment_no, s.seat_number||'-', s.full_name||s.name];
          let total = 0;
          let isFullyAbsent = true;
          activities.forEach(act => {
            const mk = allMarks.find(m => String(m.student_id) === String(s.id) && String(m.activity_no) === String(act.activity_no));
            if (mk && mk.marks !== null && mk.marks !== undefined && mk.marks !== '') { 
               const vStr = String(mk.marks).trim().toUpperCase();
               row.push(vStr);
               if (vStr !== 'AB' && vStr !== 'ABSENT') {
                  total += parseFloat(vStr) || 0;
                  isFullyAbsent = false;
               }
            }
            else row.push('-');
          });
          row.push(total); // Display student's total marks obtained
          
          let slaFinalScore = totalMaxMarks > 0 && slaMax > 0 ? Math.ceil((total/totalMaxMarks)*slaMax) : (total > 0 ? Math.ceil(total) : 0);
          
          let finalVal = { content: String(slaFinalScore), styles: { fontSize: 11 } };
          if (isFullyAbsent && total === 0) {
             finalVal = { content: '401', styles: { fontStyle: 'bold', fontSize: 11 } };
          }
          
          if (s.is_detained) {
             const detainedRow = [s.roll_no || '-', s.enrollment_no, s.seat_number || '-', s.full_name || s.name];
             detainedRow.push({ content: 'DETAINED', colSpan: activities.length + 1, styles: { halign: 'center', fontStyle: 'bold' } });
             detainedRow.push({ content: '402', styles: { fontStyle: 'bold', fontSize: 11 } });
             detainedRow.push('');
             return detainedRow;
          }
          row.push(finalVal);
          row.push('');
          return row;
        });

        doc.autoTable({ 
           head, body, startY, 
           theme: 'grid',
           rowPageBreak: 'avoid', 
           styles: { font: 'times', fontSize: 9, textColor: [0,0,0], lineColor: [0,0,0], lineWidth: 0.1, halign: 'center', valign: 'middle', cellPadding: 0.5 }, 
           headStyles: { fillColor: [255,255,255], fontStyle: 'bold' }, 
           bodyStyles: { minCellHeight: 10 },
           columnStyles: { 
             0: { cellWidth: 10 }, 
             1: { cellWidth: 21 }, 
             2: { cellWidth: 14 }, 
             3: { halign: 'left', cellWidth: 35 },
             [4+activities.length]: { cellWidth: 12 }, // Max Marks
             [4+activities.length+1]: { cellWidth: 12, fontSize: 11 } // SLA Marks (removed fontStyle: bold)
           }, 
           margin: { left: 10, right: 10 } 
        });

        addFooter(doc, doc.lastAutoTable.finalY + 10, [
           'Fractional marks shall be rounded to next full number',
           'The column is designated for specific activity.'
        ]);

        doc.save(`K6_SLA_Sheet_${course.code}.pdf`);

      } else if (report.format === 'K2-A' || report.format === 'K2-B') {
        const isLab = report.format === 'K2-A';
        const endpoint = isLab ? `/api/lab-plans?exam_id=${exam.id}&course_id=${course.id}&batch_id=${report.batch.id}` : `/api/tutorial-plans?exam_id=${exam.id}&course_id=${course.id}&batch_id=${report.batch.id}`;
        const plans = await fetch(endpoint).then(r => r.json());
        const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        
        const startY = addHeader(doc, { programme: `Diploma in ${departments.find(d => String(d.id) === String(course.dept_id))?.name || 'Engineering'}`, 
           kFormat: report.format,
           title: isLab ? 'LABORATORY PRACTICAL PLANNING' : 'TUTORIAL PLANNING',
           instituteRight: 'Institute Code: 1547',
           semesterExtraData: [`Batch: ${report.batch.batch_name}`]
        });

        const body = plans.map((p, i) => [
          i+1, p.co_mapped||'', p.title||'', p.planned_date||'', p.actual_date||'', p.remarks||''
        ]);

        doc.autoTable({ 
           head: [['Sr.', 'LLO', isLab?'Practical Title':'Tutorial Title', 'Planned Date', 'Performance Date', 'Remarks']], 
           body, 
           startY, 
           theme: 'grid',
           rowPageBreak: 'avoid', 
           styles: { font: 'times', fontSize: 9, textColor: [0,0,0], lineColor: [0,0,0], lineWidth: 0.1, halign: 'center', valign: 'middle', cellPadding: 0.5 }, 
           headStyles: { fillColor: [255,255,255], fontStyle: 'bold' }, 
           bodyStyles: { minCellHeight: 10 },
           columnStyles: { 0: { cellWidth: 10 }, 1: { halign: 'left' }, 2: { cellWidth: 60, halign: 'left' }, 3: { cellWidth: 22 }, 4: { cellWidth: 22 }, 5: { cellWidth: 30 } }, 
           margin: { left: 15, right: 15 } 
        });

        addFooter(doc, doc.lastAutoTable.finalY + 10);
        doc.save(`${report.format}_${course.code}_${report.batch.batch_name}.pdf`);
      }
    } catch(e) { console.error(e); alert(`Failed to generate PDF: ${e.message}`); }
  };

  const handleDeleteAction = async (report) => {
    const label = `${report.format} data for ${report.course.code}${report.batch ? " - " + report.batch.batch_name : ""}`;
    if (!confirm(`Are you sure you want to permanently DELETE all ${label}?\n\nThis action cannot be undone!`)) return;
    try {
        let url = "";
        if (report.format === "K3") url = `/api/lab-assessments?exam_id=${report.exam.id}&course_id=${report.course.id}`;
        else if (report.format === "K4") url = `/api/k4-assessments?exam_id=${report.exam.id}&course_id=${report.course.id}`;
        else if (report.format === "K5") url = `/api/theory-assessments?exam_id=${report.exam.id}&course_id=${report.course.id}`;
        else if (report.format === "K6") url = `/api/sla-assessments?exam_id=${report.exam.id}&course_id=${report.course.id}`;

        if (url) {
            const res = await fetch(url, { method: "DELETE" });
            if (res.ok) {
                alert("Deleted successfully");
                handleGenerateList();
            } else {
                alert("Delete failed");
            }
        }
    } catch(e) { console.error(e); alert("Delete failed"); }
  };

  return (
    <div className="p-6 space-y-6">
       <div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
          <div className="px-6 py-4 bg-gray-50 border-b border-gray-200 flex justify-between items-center">
             <h2 className="text-xl font-bold text-gray-800">📊 MSBTE Report Master (CIAAN-2023)</h2>
             <div className="flex items-center gap-2">
                <span className="flex h-3 w-3 relative">
                   <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
                   <span className="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
                </span>
                <span className="text-xs font-medium text-gray-500">System Active</span>
             </div>
          </div>

          <div className="p-6 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 bg-white">
             <div className="space-y-1.5">
                <label className="text-xs font-bold text-gray-500 uppercase ml-1">Term</label>
                <select className="w-full p-2.5 border border-gray-300 rounded-lg text-sm bg-gray-50 focus:ring-2 focus:ring-blue-500 outline-none transition-all" value={selectedExam} onChange={e => setSelectedExam(e.target.value)}>
                  {exams.map(ex => <option key={ex.id} value={ex.id}>{ex.season} {ex.year}</option>)}
                </select>
             </div>

             <div className="space-y-1.5">
                <label className="text-xs font-bold text-gray-500 uppercase ml-1">Department</label>
                <select className="w-full p-2.5 border border-gray-300 rounded-lg text-sm bg-gray-50 focus:ring-2 focus:ring-blue-500 outline-none transition-all" value={selectedDept} onChange={e => setSelectedDept(e.target.value)}>
                  <option value="">All Departments</option>
                  {departments.map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
                </select>
             </div>

             <div className="space-y-1.5">
                <label className="text-xs font-bold text-gray-500 uppercase ml-1">Semester</label>
                <select className="w-full p-2.5 border border-gray-300 rounded-lg text-sm bg-gray-50 focus:ring-2 focus:ring-blue-500 outline-none transition-all" value={selectedSem} onChange={e => setSelectedSem(e.target.value)}>
                  <option value="">All Semesters</option>
                  {[1,2,3,4,5,6].map(s => <option key={s} value={s}>Sem {s}</option>)}
                </select>
             </div>

             <div className="space-y-1.5">
                <label className="text-xs font-bold text-gray-500 uppercase ml-1">Format</label>
                <select className="w-full p-2.5 border border-gray-300 rounded-lg text-sm bg-gray-50 focus:ring-2 focus:ring-blue-500 outline-none transition-all" value={selectedFormat} onChange={e => setSelectedFormat(e.target.value)}>
                  <option value="">All K-Formats</option>
                  <option value="K2-A">K2-A (Lab Plans)</option>
                  <option value="K2-B">K2-B (Tutorial Plans)</option>
                  <option value="K3">K3 (FA-PR)</option>
                  <option value="K4">K4 (SA-PR)</option>
                  <option value="K5">K5 (FA-TH)</option>
                  <option value="K6">K6 (SLA)</option>
                </select>
             </div>

             <div className="space-y-1.5">
                <label className="text-xs font-bold text-gray-500 uppercase ml-1">Subject / Course</label>
                <select className="w-full p-2.5 border border-gray-300 rounded-lg text-sm bg-gray-50 focus:ring-2 focus:ring-blue-500 outline-none transition-all" value={selectedCourse} onChange={e => setSelectedCourse(e.target.value)}>
                  <option value="">All Subjects</option>
                  {courses.filter(c => {
                    const examObj = exams.find(e => String(e.id) === String(selectedExam));
                    const isSummer = examObj?.season === 'Summer';
                    const isEven = parseInt(c.semester) % 2 === 0;
                    if (isSummer && !isEven) return false;
                    if (!isSummer && isEven) return false;
                    if (selectedDept && String(c.dept_id) !== String(selectedDept)) return false;
                    if (selectedSem && String(c.semester) !== String(selectedSem)) return false;
                    return true;
                  }).map(c => <option key={c.id} value={c.id}>{c.code} - {c.name}</option>)}
                </select>
             </div>

             <div className="flex items-end">
                <button onClick={handleGenerateList} disabled={loading} className="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-300 text-white font-bold py-2.5 rounded-lg shadow-md transition-all flex items-center justify-center gap-2">
                  {loading ? "⌛ Loading..." : "🔍 Generate List"}
                </button>
             </div>
          </div>
       </div>

       <div className="bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden">
          <table className="min-w-full divide-y divide-gray-200">
             <thead className="bg-gray-50">
                <tr>
                   <th className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Format</th>
                   <th className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Course / Batch</th>
                   <th className="px-6 py-3 text-center text-xs font-bold text-gray-500 uppercase tracking-wider">Actions</th>
                </tr>
             </thead>
             <tbody className="bg-white divide-y divide-gray-200">
                {availableReports.map(report => (
                   <tr key={report.id} className="hover:bg-gray-50 border-l-4 border-transparent hover:border-blue-500 transition-all">
                      <td className="px-6 py-4 whitespace-nowrap">
                         <span className={`px-2 py-1 rounded text-xs font-bold ${report.format.startsWith("K2") ? "bg-gray-100 text-gray-700" : "bg-blue-100 text-blue-700"}`}>{report.format}</span>
                      </td>
                      <td className="px-6 py-4">
                         <div className="text-sm font-bold text-gray-900">{report.course.name}</div>
                         <div className="text-xs text-gray-500 font-mono">{report.course.code} {report.batch ? `| Batch: ${report.batch.batch_name}` : ""}</div>
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap text-center space-x-2">
                         <button onClick={() => handleDownloadAction(report)} className="bg-emerald-50 text-emerald-700 hover:bg-emerald-600 hover:text-white border border-emerald-200 px-3 py-1.5 rounded-lg text-xs font-bold transition-all">
                            📥 Excel
                         </button>
                         <button onClick={() => handlePdfAction(report)} className="bg-blue-50 text-blue-700 hover:bg-blue-600 hover:text-white border border-blue-200 px-3 py-1.5 rounded-lg text-xs font-bold transition-all">
                            📄 PDF
                         </button>
                         {!report.format.startsWith("K2") && (
                            <button onClick={() => handleDeleteAction(report)} className="bg-red-50 text-red-700 hover:bg-red-600 hover:text-white border border-red-200 px-3 py-1.5 rounded-lg text-xs font-bold transition-all">
                               🗑️ Delete DATA
                            </button>
                         )}
                      </td>
                   </tr>
                ))}
                {availableReports.length === 0 && !loading && (
                   <tr><td colSpan="3" className="px-6 py-20 text-center text-gray-400 font-medium italic">Select filters and click "Generate List" to see available data.</td></tr>
                )}
             </tbody>
          </table>
       </div>
    </div>
  );
};
window.ReportMaster = ReportMaster;
