const { useState, useEffect, useRef } = React;

const LP_STORAGE_KEY = 'labPlanFilters';

const LabPlanMaster = () => {
  const [courses, setCourses] = useState([]);
  const [batches, setBatches] = useState([]);
  const [exams, setExams] = useState([]);
  
  const savedFilters = (() => { try { return JSON.parse(localStorage.getItem(LP_STORAGE_KEY)) || {}; } catch(e) { return {}; } })();
  const [selectedCourse, setSelectedCourse] = useState(savedFilters.course || '');
  const [courseSearchQuery, setCourseSearchQuery] = useState('');
  const [selectedBatch, setSelectedBatch] = useState(savedFilters.batch || '');
  const [selectedExam, setSelectedExam] = useState(savedFilters.exam || '');
  const [copyFromBatch, setCopyFromBatch] = useState('');
  const [copyFromExam, setCopyFromExam] = useState('');
  
  const [plans, setPlans] = useState([]);
  const [loading, setLoading] = useState(false);
  const fileInputRef = useRef(null);
  const initialLoadDone = useRef(false);

  const [showAutoDateModal, setShowAutoDateModal] = useState(false);
  const [dbHolidays, setDbHolidays] = useState([]);
  const [autoDateConfig, setAutoDateConfig] = useState({
      startDate: '',
      endDate: '',
      weekdays: [], // e.g. [1, 2] for Monday, Tuesday (0=Sun)
      holidayDate: '',
      holidayName: '',
      holidayLevel: 'Institute'
  });

  // Persist filter selections to localStorage
  useEffect(() => {
    if (initialLoadDone.current && selectedCourse && selectedBatch && selectedExam) {
      try {
        localStorage.setItem(LP_STORAGE_KEY, JSON.stringify({ course: selectedCourse, batch: selectedBatch, exam: selectedExam }));
      } catch(e) {}
    }
  }, [selectedCourse, selectedBatch, selectedExam]);

  useEffect(() => {
    Promise.all([
      fetch('/api/courses').then(r => r.json()),
      fetch('/api/exams').then(r => r.json()),
      fetch('/api/batches').then(r => r.json())
    ]).then(([courseData, examData, batchData]) => {
      const filteredCourses = courseData.filter(c => parseFloat(c.fa_pr_max) > 0);
      setCourses(filteredCourses);
      setExams(examData);
      if(Array.isArray(batchData)) setBatches(batchData);

      const saved = (() => { try { return JSON.parse(localStorage.getItem(LP_STORAGE_KEY)) || {}; } catch(e) { return {}; } })();

      // Restore or default: course
      if (saved.course && filteredCourses.find(c => String(c.id) === String(saved.course))) {
        setSelectedCourse(saved.course);
      } else if (filteredCourses.length > 0) setSelectedCourse(filteredCourses[0].id);

      // Restore or default: exam
      if (saved.exam && examData.find(e => String(e.id) === String(saved.exam))) {
        setSelectedExam(saved.exam);
      } else if (examData.length > 0) setSelectedExam(examData[0].id);
      if (examData.length > 0) setCopyFromExam(examData[0].id);

      // Restore or default: batch
      if (saved.batch && Array.isArray(batchData) && batchData.find(b => String(b.id) === String(saved.batch))) {
        setSelectedBatch(saved.batch);
      } else if (Array.isArray(batchData) && batchData.length > 0) setSelectedBatch(batchData[0].id);

      initialLoadDone.current = true;

      // Auto-load data if we restored from saved filters
      if (saved.course && saved.batch && saved.exam) {
        const cId = saved.course, bId = saved.batch, eId = saved.exam;
        fetch(`/api/lab-plans?exam_id=${eId}&course_id=${cId}&batch_id=${bId}`)
          .then(res => res.json())
          .then(data => { if(data.length > 0) setPlans(data); else setPlans([]); });
      }
    });
  }, []);

  useEffect(() => {
    if (courses.length > 0) {
      const filtered = courses.filter(c => (c.code + ' ' + c.name).toLowerCase().includes(courseSearchQuery.toLowerCase()));
      if (filtered.length > 0 && !filtered.find(c => String(c.id) === String(selectedCourse))) {
        setSelectedCourse(filtered[0].id);
      }
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [courseSearchQuery]);

  useEffect(() => {
    try {
      const saved = localStorage.getItem('autoDateConfigPreference');
      if (saved) {
        const parsed = JSON.parse(saved);
        setAutoDateConfig(prev => ({
          ...prev,
          startDate: parsed.startDate || '',
          endDate: parsed.endDate || '',
          weekdays: parsed.weekdays || []
        }));
      }
    } catch(e) {}
  }, []);

  const fetchPlan = () => {
    if(!selectedCourse || !selectedBatch || !selectedExam) return alert("Select Term, Course, and Batch first.");
    setLoading(true);
    fetch(`/api/lab-plans?exam_id=${selectedExam}&course_id=${selectedCourse}&batch_id=${selectedBatch}`)
      .then(res => res.json())
      .then(data => {
         if(data.length > 0) setPlans(data);
         else setPlans([]);
         setLoading(false);
      });
  };

  const handleCopyFromBatch = () => {
     if(!selectedCourse || !copyFromBatch || !copyFromExam) return alert("Select a Term, Course, and Source Batch to copy from");
     if(copyFromBatch === selectedBatch && copyFromExam === selectedExam) return alert("Cannot copy from the same active batch within the same term.");
     setLoading(true);
     fetch(`/api/lab-plans?exam_id=${copyFromExam}&course_id=${selectedCourse}&batch_id=${copyFromBatch}`)
       .then(r=>r.json())
       .then(data => {
          if(data.length > 0) {
              // Strip database IDs and foreign keys so the cloned data saves as new records
              const freshCopy = data.map(d => ({
                practical_no: d.practical_no,
                title: d.title,
                co_mapped: d.co_mapped,
                related_co: d.related_co,
                planned_date: d.planned_date,
                actual_date: d.actual_date,
                remarks: d.remarks,
                self_learning: d.self_learning
              }));
              if (plans.length > 0) {
                 if(window.confirm("Overwrite current grid with practicals from selected batch?")) {
                    setPlans(freshCopy);
                 }
              } else setPlans(freshCopy);
          } else {
              alert("No lab plan found for the selected Target Batch to copy from.");
          }
          setLoading(false);
       });
  };

  const handleAddRow = () => {
     setPlans([...plans, { practical_no: plans.length + 1, title: '', co_mapped: '', related_co: '', planned_date: '', actual_date: '', remarks: '', self_learning: '' }]);
  };

  const handleChange = (index, field, value) => {
     const newPlans = [...plans];
     newPlans[index][field] = value;
     if (field === 'planned_date' && !newPlans[index].actual_date) {
       newPlans[index].actual_date = value;
     }
     setPlans(newPlans);
  };
  
  const handleDeleteRow = (index) => {
     const newPlans = plans.filter((_, i) => i !== index);
     // Auto-readjust practical numbers
     const adjusted = newPlans.map((p, i) => ({...p, practical_no: i + 1}));
     setPlans(adjusted);
  };

  const handleClearBoard = () => {
     if(window.confirm("Are you sure you want to clear the entire matrix? Ensure you click 'Save Dashboard' afterward to delete it from the database.")) {
         setPlans([]);
     }
  };

  const handleSave = () => {
     if(!selectedCourse || !selectedBatch || !selectedExam) return alert("Select Term, Course, and Batch");
     
     setLoading(true);
     fetch('/api/lab-plans', {
         method: 'POST',
         headers: { 'Content-Type': 'application/json' },
         body: JSON.stringify({ exam_id: selectedExam, course_id: selectedCourse, batch_id: selectedBatch, plans })
     })
     .then(res => res.json())
     .then(data => {
         setLoading(false);
         if(data.success) alert("Lab Plan synchronized successfully!");
     }).catch(err => { setLoading(false); alert("Failed saving"); });
  };

  useEffect(() => {
    if (showAutoDateModal && selectedCourse) {
       const fetchCb = async () => {
          try {
             // Fetch course to get dept_id
             const courseRes = await fetch('/api/courses');
             const allCourses = await courseRes.json();
             const c = allCourses.find(x => x.id === selectedCourse);
             
             let q = `?course_id=${selectedCourse}`;
             if (c && c.dept_id) q += `&dept_id=${c.dept_id}`;
             
             const hRes = await fetch(`/api/holidays${q}`);
             if (hRes.ok) {
                const holidays = await hRes.json();
                setDbHolidays(holidays);
             }
          } catch(e) { console.error('Failed fetching holidays', e); }
       };
       fetchCb();
    }
  }, [showAutoDateModal, selectedCourse]);

  const handleAddHoliday = async () => {
    if(!autoDateConfig.holidayDate || !autoDateConfig.holidayName) return alert('Date and Name required');
    try {
      // Find course to get dept_id
      const c = courses.find(x => x.id === selectedCourse);
      
      const payload = {
         date: autoDateConfig.holidayDate,
         name: autoDateConfig.holidayName,
         level: autoDateConfig.holidayLevel,
         course_id: autoDateConfig.holidayLevel === 'Individual' ? selectedCourse : null,
         dept_id: autoDateConfig.holidayLevel === 'Department' ? (c?.dept_id || null) : null
      };

      const res = await fetch('/api/holidays', {
         method: 'POST',
         headers: { 'Content-Type': 'application/json' },
         body: JSON.stringify(payload)
      });
      if (res.ok) {
         const newH = await res.json();
         setDbHolidays([...dbHolidays, newH]);
         setAutoDateConfig({...autoDateConfig, holidayDate: '', holidayName: ''});
      } else {
         alert('Failed to save holiday');
      }
    } catch(e) { console.error(e); }
  };

  const handleRemoveHoliday = async (id) => {
    try {
       await fetch(`/api/holidays/${id}`, { method: 'DELETE' });
       setDbHolidays(dbHolidays.filter(h => h.id !== id));
    } catch(e) { console.error(e); }
  };

  const handleToggleWeekday = (dayIdx) => {
    const nextDays = autoDateConfig.weekdays.includes(dayIdx) ? autoDateConfig.weekdays.filter(d => d !== dayIdx) : [...autoDateConfig.weekdays, dayIdx];
    setAutoDateConfig({...autoDateConfig, weekdays: nextDays});
  };

  const handleAutoMapSubmit = () => {
      if(!autoDateConfig.startDate || !autoDateConfig.endDate) return alert("Select Start and End dates");
      if(autoDateConfig.weekdays.length === 0) return alert("Select at least one valid weekday");
      
      try {
        localStorage.setItem('autoDateConfigPreference', JSON.stringify({
          startDate: autoDateConfig.startDate,
          endDate: autoDateConfig.endDate,
          weekdays: autoDateConfig.weekdays
        }));
      } catch (e) {}

      let index = 0;
     let currentDate = new Date(autoDateConfig.startDate);
     const end = new Date(autoDateConfig.endDate);
     
     currentDate.setHours(0,0,0,0);
     end.setHours(0,0,0,0);
     
     const newPlans = [...plans];
     
     while (currentDate <= end && index < newPlans.length) {
       const day = currentDate.getDay();
       const y = currentDate.getFullYear();
       const m = String(currentDate.getMonth() + 1).padStart(2, '0');
       const d = String(currentDate.getDate()).padStart(2, '0');
       const dateStr = `${y}-${m}-${d}`;
       
       const isHoliday = dbHolidays.some(h => h.date === dateStr);

       if (autoDateConfig.weekdays.includes(day) && !isHoliday) {
          newPlans[index].planned_date = dateStr;
          newPlans[index].actual_date = dateStr;
          index++;
       }
       currentDate.setDate(currentDate.getDate() + 1);
     }
     
     setPlans(newPlans);
     setShowAutoDateModal(false);
     if (index < newPlans.length) {
        alert(`Warning: Only sufficient valid dates to fill the first ${index} practicals. Choose a longer range or more weekdays.`);
     }
  };

  const getNextValidDate = (startDate) => {
     let currentDate = new Date(startDate);
     currentDate.setDate(currentDate.getDate() + 1); // Start checking from next day
     currentDate.setHours(0,0,0,0);
     
     // Safeguard loop to prevent infinite searching
     for(let i=0; i<365; i++) {
        const day = currentDate.getDay();
        const y = currentDate.getFullYear();
        const m = String(currentDate.getMonth() + 1).padStart(2, '0');
        const d = String(currentDate.getDate()).padStart(2, '0');
        const dateStr = `${y}-${m}-${d}`;
        
        const isHoliday = dbHolidays.some(h => h.date === dateStr);
        if (autoDateConfig.weekdays.includes(day) && !isHoliday) {
            return dateStr;
        }
        currentDate.setDate(currentDate.getDate() + 1);
     }
     return null;
  };

  const handleShiftDate = (index, field) => {
     if(autoDateConfig.weekdays.length === 0) {
         alert("Please configure valid weekdays via 'Auto Map Dates' first.");
         return;
     }

     const basisDate = plans[index][field] || (index === 0 ? new Date().toISOString().split('T')[0] : plans[index-1][field]);
     if(!basisDate) {
         alert("Cannot calculate next date because there is no basis date assigned.");
         return;
     }

     const nextDate = getNextValidDate(basisDate);
     if(!nextDate) return alert("Could not find a valid future date within the next year.");

     const cascade = window.confirm(`Calculated next available date: ${nextDate}\n\nDo you want to cascade this shift to ALL subsequent practicals? (Click Cancel to apply ONLY to this single row)`);

     const newPlans = [...plans];
     if(cascade) {
         let currentAssignDate = nextDate;
         for(let i=index; i<newPlans.length; i++) {
             newPlans[i][field] = currentAssignDate;
             if (field === 'planned_date' && !newPlans[i].actual_date) {
                 newPlans[i].actual_date = currentAssignDate;
             }
             const nextIter = getNextValidDate(currentAssignDate);
             if(!nextIter) break;
             currentAssignDate = nextIter;
         }
     } else {
         newPlans[index][field] = nextDate;
         if (field === 'planned_date' && !newPlans[index].actual_date) {
             newPlans[index].actual_date = nextDate;
         }
     }
     setPlans(newPlans);
  };



  const parseExcelDate = (val) => {
    if (!val) return '';
    if (typeof val === 'number') {
        const date = new Date(Math.round((val - 25569) * 86400 * 1000));
        return date.toISOString().split('T')[0];
    }
    const str = String(val).trim();
    if (str.match(/^\d{4}-\d{2}-\d{2}$/)) return str;
    return '';
  };

  const parseExcelSyllabus = (e) => {
    const file = e.target.files[0];
    if (!file) return;
    
    const reader = new FileReader();
    reader.onload = (evt) => {
      const data = evt.target.result;
      const workbook = window.XLSX.read(data, { type: 'binary' });
      const sheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[sheetName];
      const json = window.XLSX.utils.sheet_to_json(worksheet, { header: 1 });
      
      const extracted = [];
      let counter = 1;
      let isNewTemplate = false;
      if (json.length > 0 && Array.isArray(json[0])) {
         const headerStr = json[0].join(' ').toLowerCase();
         if (headerStr.includes('related co')) isNewTemplate = true;
      }
      
      for (let i = Math.max(0, startIndex); i < json.length; i++) {
         const row = json[i];
         if (!row || row.length < 2) continue;
         
         let lloStr = '';
         let titleStr = '';
         let planned = '';
         let actual = '';
         let remarks = '';
         let self = '';
         let related_co = null;
         
         const possibleNumber = parseInt(row[0] || row[1]);
         const hasStructuredCols = row.length >= 3 && !isNaN(parseInt(row[0])) && String(row[0]).trim() !== '';

         if (hasStructuredCols || startIndex === 1) {
             if (isNewTemplate) {
                 related_co = row[1] ? String(row[1]) : null;
                 lloStr = String(row[2] || '');
                 titleStr = String(row[3] || '');
                 planned = parseExcelDate(row[4]);
                 actual = parseExcelDate(row[5]);
                 remarks = String(row[6] || '');
                 self = String(row[7] || '');
             } else {
                 lloStr = String(row[1] || '');
                 titleStr = String(row[2] || '');
                 planned = parseExcelDate(row[3]);
                 actual = parseExcelDate(row[4]);
                 remarks = String(row[5] || '');
                 self = String(row[6] || '');
             }
         } else if (!isNaN(possibleNumber) && String(row[1] || '').length > 5) {
             titleStr = String(row[1] || row[2] || '');
             lloStr = row[2] && String(row[2]).length < 6 ? String(row[2]) : String(row[3] || '');
         }

         if (titleStr.length > 3) {
             extracted.push({
                 practical_no: counter++,
                 title: titleStr,
                 co_mapped: lloStr,
                 related_co: related_co || '',
                 planned_date: planned,
                 actual_date: actual,
                 remarks: remarks,
                 self_learning: self
             });
         }
      }
      
      if(extracted.length > 0) {
         setPlans(extracted);
      } else {
         alert("Could not detect standard Practical rows in Excel. Ensure columns have a Number and a Title string.");
      }
      fileInputRef.current.value = ''; // reset
    };
    reader.readAsBinaryString(file);
  };

  const handleDownloadTemplate = () => {
    const wsData = [
      ['Sr. No.', 'Related CO', 'LLO', 'Practical Title / Tutorial Title', 'Planned Date (YYYY-MM-DD)', 'Performance Date (YYYY-MM-DD)', 'Remarks', 'Related self-learning']
    ];
    wsData.push([1, '1, 2', '2.1 Implement programs to evaluate...', 'Example Practical Title', '2023-08-15', '2023-08-20', 'Setup done', 'Read chap 2']);
    const ws = window.XLSX.utils.aoa_to_sheet(wsData);
    
    // Apply styling cleanly
    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: true }
       };
       if (cellAddress.r === 0) ws[key].s.font = { bold: true };
       if (cellAddress.r >= 0 && cellAddress.r <= 6) {
           ws[key].s.border = { top: {style:'thin'}, bottom: {style:'thin'}, left: {style:'thin'}, right: {style:'thin'} };
       }
    }
    
    ws['!cols'] = [{wch: 8}, {wch: 15}, {wch: 35}, {wch: 40}, {wch: 25}, {wch: 25}, {wch: 20}, {wch: 20}];
    const wb = window.XLSX.utils.book_new();
    window.XLSX.utils.book_append_sheet(wb, ws, "Template");
    window.XLSX.writeFile(wb, "LabPlan_Import_Template.xlsx");
  };

  const handleExportExcel = () => {
    if (!selectedCourse || !selectedBatch || !selectedExam) return alert('Select Term, Course, and Batch first.');
    if (plans.length === 0) return alert('No plans to export!');
    
    const courseObj = courses.find(c => String(c.id) === String(selectedCourse));
    const batchObj = batches.find(b => String(b.id) === String(selectedBatch));
    const examObj = exams.find(e => String(e.id) === String(selectedExam));
    
    const wsData = [];
    
    // Header
    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 = examObj ? (examObj.season === 'Winter' ? `${examObj.year}-${String(Number(examObj.year)+1).slice(-2)}` : `${Number(examObj.year)-1}-${String(examObj.year).slice(-2)}`) : '';
    wsData.push(['Academic Year:', acYear, '', '', '', '', '']);
    wsData.push(['Programme:', '', 'Course: ' + (courseObj ? courseObj.name : ''), '', '', 'Course Code:', courseObj ? courseObj.code : '']);
    wsData.push(['Semester:', courseObj ? courseObj.semester + 'K' : '', '', '', '', 'Batch:', batchObj ? batchObj.batch_name : '']);
    wsData.push([]);
    
    // Table Header
    wsData.push(['Sr. No.', 'LLO', 'Practical Title / Tutorial Title', 'Planned Date', 'Performance Date', 'Remarks', 'Related self-learning (if any)']);
    
    // Rows
    plans.forEach(p => {
       wsData.push([
          p.practical_no || '',
          p.co_mapped || '',
          p.title || '',
          p.planned_date || '',
          p.actual_date || '',
          p.remarks || '',
          p.self_learning || ''
       ]);
    });
    
    // Footer
    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:']);
    
    // Create sheet
    const ws = window.XLSX.utils.aoa_to_sheet(wsData);
    
    // Apply Stylings
    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'} };
       }
    }
    
    // Add custom merges matching the visual flow
    ws['!merges'] = [
      { s: {r:4, c:2}, e: {r:4, c: 5} }, // MSBTE title center
      { s: {r:5, c:2}, e: {r:5, c: 5} }, // PLANNING center
      { s: {r:3, c:0}, e: {r:3, c: 2} }  // AICTE
    ];
    
    // Basic Column Widths
    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_${courseObj?.code || 'Draft'}_${batchObj?.batch_name || ''}.xlsx`);
  };

  return (
    <div className="flex flex-col gap-6 animate-fade-in-up pb-12">
      <div className="bg-white p-5 rounded-2xl shadow-sm border border-gray-200">
        <div>
          <h1 className="text-2xl font-bold text-gray-900 tracking-tight">Format K2-A: Teaching Plan</h1>
          <p className="text-sm text-gray-500 mt-1">Map out practical schedules linking Title, Outcomes, and temporal tracking.</p>
        </div>
      </div>

      <div className="bg-white border text-sm text-gray-700 border-gray-200 flex flex-wrap gap-4 items-end p-4 rounded-xl shadow-sm">
         <div className="w-[180px]">
           <label className="text-[10px] font-bold text-gray-500 uppercase block mb-1">Target Academic Term</label>
           <select value={selectedExam} onChange={e=>setSelectedExam(e.target.value)} className="w-full border border-gray-300 rounded px-3 py-2 outline-none focus:border-red-500 font-medium bg-red-50/20 border-l-4 border-l-red-500 text-red-900">
             <option value="">Select Term...</option>
             {exams.map(e => <option key={e.id} value={e.id}>{e.season} {e.year}</option>)}
           </select>
         </div>
         <div className="w-1/4 min-w-[200px]">
           <label className="text-[10px] font-bold text-gray-500 uppercase block mb-1">Target Course</label>
           <input 
              type="text" 
              placeholder="Search Code/Name..." 
              value={courseSearchQuery} 
              onChange={e => setCourseSearchQuery(e.target.value)} 
              className="w-full border-b border-gray-200 px-1 py-0.5 text-xs bg-white mb-1 focus:border-blue-500 outline-none"
           />
           <select value={selectedCourse} onChange={e=>setSelectedCourse(e.target.value)} className="w-full border border-gray-300 rounded px-3 py-2 outline-none focus:border-blue-500 font-medium">
             {courses.filter(c => (c.code + ' ' + c.name).toLowerCase().includes(courseSearchQuery.toLowerCase())).map(c => <option key={c.id} value={c.id}>{c.code} - {c.name}</option>)}
           </select>
         </div>
         <div className="w-1/4 min-w-[150px]">
           <label className="text-[10px] font-bold text-gray-500 uppercase block mb-1">Target Batch</label>
           <select value={selectedBatch} onChange={e=>setSelectedBatch(e.target.value)} className="w-full border border-gray-300 rounded px-3 py-2 outline-none focus:border-blue-500 font-medium font-mono">
             {batches.map(b => <option key={b.id} value={b.id}>{b.batch_name}</option>)}
           </select>
         </div>
         <button onClick={fetchPlan} disabled={loading} className="bg-gray-900 hover:bg-black text-white px-5 py-2 rounded shadow transition font-bold">
           Load Matrix
         </button>
         
         <div className="w-[1px] h-10 bg-gray-200 mx-2 hidden sm:block"></div>
         
         <div className="w-1/4 min-w-[150px]">
           <label className="text-[10px] font-bold text-emerald-600 uppercase block mb-1">Copy List From Term</label>
           <select value={copyFromExam} onChange={e=>setCopyFromExam(e.target.value)} className="w-full border border-emerald-300 rounded px-3 py-2 outline-none focus:border-emerald-500 font-medium bg-emerald-50/20 text-emerald-900 border-l-4 border-l-emerald-500">
             <option value="">Select Term...</option>
             {exams.map(e => <option key={e.id} value={e.id}>{e.season} {e.year}</option>)}
           </select>
         </div>

         <div className="w-1/4 min-w-[150px]">
           <label className="text-[10px] font-bold text-emerald-600 uppercase block mb-1">Copy List From Batch</label>
           <select value={copyFromBatch} onChange={e=>setCopyFromBatch(e.target.value)} className="w-full border border-emerald-300 rounded px-3 py-2 outline-none focus:border-emerald-500 font-medium font-mono text-emerald-800 bg-emerald-50/20">
             <option value="">Select Source...</option>
             {batches.map(b => <option key={b.id} value={b.id}>{b.batch_name}</option>)}
           </select>
         </div>
         <button onClick={handleCopyFromBatch} disabled={loading} className="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 rounded shadow transition font-bold">
           Clone
         </button>
      </div>

      <div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
         <div className="px-5 py-4 bg-gray-50 border-b border-gray-200 flex flex-wrap justify-between items-center gap-4">
             <div className="flex gap-2">
                 <button onClick={handleAddRow} className="bg-white border border-gray-300 text-gray-700 hover:bg-gray-100 px-4 py-1.5 rounded text-xs font-bold uppercase tracking-wider shadow-sm transition">
                    + Insert Practical
                 </button>
                 <button onClick={() => setShowAutoDateModal(true)} className="bg-purple-50 text-purple-700 border border-purple-200 hover:bg-purple-100 px-4 py-1.5 rounded text-xs font-bold uppercase tracking-wider shadow-sm transition">
                    Auto Map Dates
                 </button>
                 <button onClick={handleDownloadTemplate} className="bg-white border border-gray-300 text-gray-700 hover:bg-gray-100 px-4 py-1.5 rounded text-xs font-bold uppercase tracking-wider shadow-sm transition flex gap-1 items-center">
                    Get Template
                 </button>
                 <div className="relative">
                    <input type="file" ref={fileInputRef} onChange={parseExcelSyllabus} accept=".xlsx,.xls" className="hidden" />
                    <button onClick={() => fileInputRef.current.click()} className="bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 px-4 py-1.5 rounded text-xs font-bold uppercase tracking-wider shadow-sm transition flex gap-1 items-center">
                       <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path></svg>
                       Import Excel
                    </button>
                 </div>
                 <button onClick={handleExportExcel} className="bg-white border border-teal-200 text-teal-700 hover:bg-teal-50 px-4 py-1.5 rounded text-xs font-bold uppercase tracking-wider shadow-sm transition flex gap-1 items-center">
                    Print K2-A Form
                 </button>
             </div>
             <div className="flex gap-2">
                 <button onClick={handleClearBoard} disabled={loading || plans.length===0} className="bg-red-50 hover:bg-red-100 text-red-600 border border-red-200 font-bold px-6 py-2 rounded shadow-sm transition text-sm">
                    Clear Master Plan
                 </button>
                 <button onClick={handleSave} disabled={loading} className="bg-emerald-600 hover:bg-emerald-700 text-white font-bold px-6 py-2 rounded shadow transition text-sm">
                    Commit & Lock Plan
                 </button>
             </div>
         </div>

         <div className="overflow-x-auto">
            <table className="w-full text-left text-sm text-gray-700">
               <thead className="bg-gray-100/50 text-gray-500 font-bold uppercase text-[10px] tracking-widest border-b border-gray-200">
                   <tr>
                     <th className="px-4 py-3 text-center w-12 text-xs">Sr. No.</th>
                     <th className="px-4 py-3 min-w-[100px] border-l border-gray-100 text-center">Related CO</th>
                     <th className="px-4 py-3 min-w-[150px] border-l border-r border-gray-100">LLO</th>
                     <th className="px-4 py-3 min-w-[200px]">Practical Title / Tutorial Title</th>
                     <th className="px-4 py-3 text-center bg-blue-50/50 w-32">Planned Date</th>
                     <th className="px-4 py-3 text-center bg-purple-50/50 w-32">Performance Date</th>
                     <th className="px-4 py-3 text-center border-l border-r border-gray-100 w-32">Remarks</th>
                     <th className="px-4 py-3 text-center border-r border-gray-100 w-32">Related self-learning</th>
                     <th className="px-4 py-3 w-10 text-center"></th>
                  </tr>
               </thead>
               <tbody className="divide-y divide-gray-100">
                  {plans.map((p, index) => (
                     <tr key={index} className="hover:bg-gray-50 group">
                        <td className="px-4 py-2 text-center font-mono font-bold text-gray-400 text-xs">{p.practical_no}</td>
                        <td className="px-4 py-2 border-l border-gray-100 align-top">
                           <input type="text" value={p.related_co || ''} onChange={e=>handleChange(index, 'related_co', e.target.value)} className="w-full text-center outline-none bg-transparent border-b border-transparent focus:border-blue-400 py-1 text-sm text-gray-700 transition-colors" placeholder="e.g. 1, 2" />
                        </td>
                        <td className="px-4 py-2 border-l border-r border-gray-100 align-top">
                           <textarea value={p.co_mapped || ''} onChange={e=>handleChange(index, 'co_mapped', e.target.value)} rows={Math.max(2, Math.ceil((p.co_mapped||'').length / 40))} className="w-full resize-none outline-none bg-transparent border-b border-transparent focus:border-blue-400 py-1 text-sm text-gray-700 transition-colors whitespace-pre-wrap break-words" placeholder="e.g. 2.1 Implement programs to evaluate..." />
                        </td>
                        <td className="px-4 py-2">
                           <textarea value={p.title || ''} onChange={e=>handleChange(index, 'title', e.target.value)} rows={Math.max(2, Math.ceil((p.title||'').length / 50))} className="w-full resize-none outline-none bg-transparent border-b border-transparent focus:border-blue-400 py-1 text-sm font-medium text-gray-900 transition-colors whitespace-pre-wrap break-words" placeholder="Type experiment title..." />
                        </td>
                        <td className="px-4 py-2 bg-blue-50/20 text-center">
                           <div className="flex flex-col items-center gap-1">
                               <input type="date" value={p.planned_date || ''} onChange={e=>handleChange(index, 'planned_date', e.target.value)} className="bg-transparent border-none outline-none text-xs text-blue-900 font-bold cursor-pointer" />
                               <button onClick={() => handleShiftDate(index, 'planned_date')} className="bg-blue-100 hover:bg-blue-200 text-blue-700 text-[9px] px-2 py-0.5 rounded uppercase font-bold tracking-wider shadow-sm" title="Calculate next valid date & cascade">⇥ Shift</button>
                           </div>
                        </td>
                        <td className="px-4 py-2 bg-purple-50/20 text-center">
                           <div className="flex flex-col items-center gap-1">
                               <input type="date" value={p.actual_date || ''} onChange={e=>handleChange(index, 'actual_date', e.target.value)} className="bg-transparent border-none outline-none text-xs text-purple-900 font-bold cursor-pointer" />
                               <button onClick={() => handleShiftDate(index, 'actual_date')} className="bg-purple-100 hover:bg-purple-200 text-purple-700 text-[9px] px-2 py-0.5 rounded uppercase font-bold tracking-wider shadow-sm" title="Calculate next valid date & cascade">⇥ Shift</button>
                           </div>
                        </td>
                        <td className="px-4 py-2 text-center border-l border-r border-gray-100">
                           <input type="text" value={p.remarks || ''} onChange={e=>handleChange(index, 'remarks', e.target.value)} className="w-full outline-none bg-transparent border-b border-transparent focus:border-blue-400 py-1 text-xs text-center" placeholder="Remarks" />
                        </td>
                        <td className="px-4 py-2 text-center border-r border-gray-100">
                           <input type="text" value={p.self_learning || ''} onChange={e=>handleChange(index, 'self_learning', e.target.value)} className="w-full outline-none bg-transparent border-b border-transparent focus:border-blue-400 py-1 text-xs text-center" placeholder="Self-learning" />
                        </td>
                        <td className="px-4 py-2 text-center">
                           <button onClick={()=>handleDeleteRow(index)} className="text-gray-300 hover:text-red-500 transition opacity-0 group-hover:opacity-100 px-2 py-1">✕</button>
                        </td>
                     </tr>
                  ))}
                  {plans.length === 0 && (
                     <tr><td colSpan="6" className="text-center py-12 text-gray-400 italic">No practicals defined. Use the importer or insert rows manually.</td></tr>
                  )}
               </tbody>
            </table>
         </div>
      </div>

      {showAutoDateModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-gray-900/40 backdrop-blur-sm animate-fade-in">
          <div className="bg-white rounded-2xl shadow-xl w-full max-w-lg overflow-hidden flex flex-col max-h-[90vh]">
            <div className="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50/50">
               <div>
                  <h3 className="font-bold text-gray-900">Auto Assign Dates</h3>
                  <p className="text-xs text-gray-500 mt-1">Automatically map dates sequentially ignoring holidays.</p>
               </div>
               <button onClick={() => setShowAutoDateModal(false)} className="text-gray-400 hover:text-gray-600">✕</button>
            </div>
            
            <div className="p-6 overflow-y-auto flex flex-col gap-6">
               <div className="flex gap-4">
                  <div className="flex-1">
                     <label className="text-xs font-bold text-gray-700 uppercase block mb-2">Start Date</label>
                     <input type="date" value={autoDateConfig.startDate} onChange={e=>setAutoDateConfig({...autoDateConfig, startDate: e.target.value})} className="w-full border border-gray-300 rounded px-3 py-2 text-sm focus:border-purple-500 outline-none" />
                  </div>
                  <div className="flex-1">
                     <label className="text-xs font-bold text-gray-700 uppercase block mb-2">End Date</label>
                     <input type="date" value={autoDateConfig.endDate} onChange={e=>setAutoDateConfig({...autoDateConfig, endDate: e.target.value})} className="w-full border border-gray-300 rounded px-3 py-2 text-sm focus:border-purple-500 outline-none" />
                  </div>
               </div>
               
               <div>
                  <label className="text-xs font-bold text-gray-700 uppercase block mb-2">Valid Weekdays</label>
                  <div className="flex flex-wrap gap-2">
                     {['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((d, i) => (
                        <button key={i} onClick={() => handleToggleWeekday(i)} 
                            className={`px-3 py-1.5 rounded text-sm font-medium border ${autoDateConfig.weekdays.includes(i) ? 'bg-purple-100 border-purple-300 text-purple-800' : 'bg-white border-gray-300 text-gray-500 hover:bg-gray-50'}`}>
                           {d}
                        </button>
                     ))}
                  </div>
               </div>
               
               <div className="border border-gray-200 rounded-lg p-4 bg-gray-50/50">
                  <label className="text-xs font-bold text-gray-700 uppercase block mb-3">Database Holidays (Skip Dates)</label>
                  <div className="flex flex-col gap-2 mb-4">
                     <div className="flex gap-2">
                         <input type="date" value={autoDateConfig.holidayDate} onChange={e=>setAutoDateConfig({...autoDateConfig, holidayDate:e.target.value})} className="border border-gray-300 rounded px-2 py-1.5 text-sm focus:border-purple-500 outline-none w-32" />
                         <input type="text" placeholder="Holiday Name (e.g. Diwali)" value={autoDateConfig.holidayName} onChange={e=>setAutoDateConfig({...autoDateConfig, holidayName:e.target.value})} className="flex-1 border border-gray-300 rounded px-2 py-1.5 text-sm focus:border-purple-500 outline-none" />
                     </div>
                     <div className="flex gap-2 items-center">
                         <select value={autoDateConfig.holidayLevel} onChange={e=>setAutoDateConfig({...autoDateConfig, holidayLevel:e.target.value})} className="border border-gray-300 rounded px-2 py-1.5 text-sm outline-none flex-1">
                            <option value="Institute">Institute Level (Common to All)</option>
                            <option value="Department">Department Level</option>
                            <option value="Individual">Individual Level</option>
                         </select>
                         <button onClick={handleAddHoliday} className="bg-gray-800 text-white px-4 rounded py-1.5 text-sm font-bold hover:bg-gray-700">Add to DB</button>
                     </div>
                  </div>
                  {dbHolidays.length > 0 ? (
                     <div className="flex flex-col gap-2 max-h-40 overflow-y-auto pr-1">
                        {dbHolidays.map(h => (
                           <div key={h.id} className="bg-white border border-gray-200 text-gray-700 text-xs px-3 py-2 rounded flex justify-between items-center shadow-sm">
                              <div className="flex items-center gap-3">
                                  <span className="font-bold text-red-600">{h.date}</span>
                                  <span className="font-semibold">{h.name}</span>
                                  <span className="text-[10px] bg-gray-100 px-2 py-0.5 rounded-full text-gray-500 border border-gray-200">{h.level}</span>
                              </div>
                              <button onClick={()=>handleRemoveHoliday(h.id)} className="text-gray-400 hover:text-red-600 font-bold px-2 py-1 rounded hover:bg-red-50">✕</button>
                           </div>
                        ))}
                     </div>
                  ) : (
                     <div className="text-xs text-gray-400 italic">No holidays stored in database yet.</div>
                  )}
               </div>
            </div>
            
            <div className="px-6 py-4 border-t border-gray-100 bg-gray-50 flex justify-end gap-2">
               <button onClick={() => setShowAutoDateModal(false)} className="px-4 py-2 text-sm font-bold text-gray-600 hover:bg-gray-200 rounded">Cancel</button>
               <button onClick={handleAutoMapSubmit} className="px-4 py-2 text-sm font-bold bg-purple-600 hover:bg-purple-700 text-white rounded shadow">Generate Dates</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};
window.LabPlanMaster = LabPlanMaster;
