import React, { useEffect, useState, useMemo } from 'react';
import {
  Button,
  Col,
  DatePicker,
  Input,
  Popover,
  Row,
  Space,
  Spin,
  Table,
  Tag,
  message,
} from 'antd';
import {
  FormOutlined,
  TableOutlined,
  TeamOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
  ClockCircleOutlined,
  EditOutlined,
  DownloadOutlined,
  CalendarOutlined,
} from '@ant-design/icons';
import dayjs, { type Dayjs } from 'dayjs';
import { AppContainer } from '../../components/AppContainer';
import jwtAxios from '../../api/axiosInstance';
import { ENDPOINTS } from '../../api/endpoints';
import SummaryCard from '../../components/SummaryCard';

// Types
import type {
  AttendanceStatusType,
  DailyAttendanceItem,
  SummaryData,
  MonthlyEmployee,
  SingleEmployeeSummary,
  AttendanceExportConfig,
} from './types';

// Modal Components
import { MarkAttendanceModal } from './components/MarkAttendanceModal';
import { MonthlyMatrixModal } from './components/MonthlyMatrixModal';
import { SingleEmployeeMatrixModal } from './components/SingleEmployeeMatrixModal';
import { ExportAttendanceModal } from './components/ExportAttendanceModal';
import { EditSingleAttendanceModal } from './components/EditSingleAttendanceModal';

export const Attendance: React.FC = () => {
  // Global States
  const [selectedDate, setSelectedDate] = useState<Dayjs>(dayjs());
  const [searchText, setSearchText] = useState<string>('');
  const [loading, setLoading] = useState<boolean>(false);
  const [saving, setSaving] = useState<boolean>(false);

  // Attendance Data
  const [attendanceItems, setAttendanceItems] = useState<DailyAttendanceItem[]>([]);
  const [summary, setSummary] = useState<SummaryData>({
    totalEmployees: 0,
    present: 0,
    absent: 0,
    halfDay: 0,
    attendanceRate: 0,
  });

  // Modal Visibility States
  const [isMarkModalOpen, setIsMarkModalOpen] = useState<boolean>(false);
  const [isMatrixModalOpen, setIsMatrixModalOpen] = useState<boolean>(false);
  const [editEmployee, setEditEmployee] = useState<DailyAttendanceItem | null>(null);
  const [isSingleEditModalOpen, setIsSingleEditModalOpen] = useState<boolean>(false);

  // Single Employee Matrix & Calendar Modal State
  const [singleEmployeeId, setSingleEmployeeId] = useState<string | null>(null);
  const [singleEmployeeName, setSingleEmployeeName] = useState<string>('');
  const [singleEmployeeData, setSingleEmployeeData] = useState<SingleEmployeeSummary | null>(null);
  const [isSingleMatrixModalOpen, setIsSingleMatrixModalOpen] = useState<boolean>(false);
  const [singleMatrixLoading, setSingleMatrixLoading] = useState<boolean>(false);
  const [singleMatrixMonth, setSingleMatrixMonth] = useState<Dayjs>(dayjs());

  // Export Modal & Options State
  const [isExportModalOpen, setIsExportModalOpen] = useState<boolean>(false);
  const [exportLoading, setExportLoading] = useState<boolean>(false);
  const [employeeOptions, setEmployeeOptions] = useState<Array<{ id: string | number; name: string; employeeCode?: string }>>([]);
  useEffect(() => {
    const fetchExportFiltersData = async () => {
      try {
        const empRes = await jwtAxios.get(ENDPOINTS.EMPLOYEES);

        if (empRes.data?.result) {
          const list = Array.isArray(empRes.data.result)
            ? empRes.data.result
            : empRes.data.result.items || [];
          setEmployeeOptions(
            list.map((emp: any) => ({
              id: emp.id,
              name: emp.name,
              employeeCode: emp.employeeCode,
            }))
          );
        }
      } catch (err) {
        // Silently catch and fallback to local attendance items
      }
    };
    fetchExportFiltersData();
  }, []);

  const computedEmployees = useMemo(() => {
    if (employeeOptions.length > 0) return employeeOptions;
    return attendanceItems.map((item) => ({ id: item.employeeId, name: item.name }));
  }, [employeeOptions, attendanceItems]);

  // All Employees Monthly Matrix States
  const [calendarMonth, setCalendarMonth] = useState<Dayjs>(dayjs());
  const [monthlyData, setMonthlyData] = useState<MonthlyEmployee[]>([]);
  const [monthlyLoading, setMonthlyLoading] = useState<boolean>(false);
  const [matrixSearchText, setMatrixSearchText] = useState<string>('');

  const filteredMonthlyData = useMemo(() => {
    if (!matrixSearchText.trim()) return monthlyData;
    const q = matrixSearchText.toLowerCase();
    return monthlyData.filter(
      (emp) =>
        emp.name.toLowerCase().includes(q) ||
        (emp.designation && emp.designation.toLowerCase().includes(q))
    );
  }, [monthlyData, matrixSearchText]);

  // Client-side instant filter for daily attendance display table
  const filteredDailyAttendance = useMemo(() => {
    if (!searchText.trim()) return attendanceItems;
    const q = searchText.toLowerCase().trim();
    return attendanceItems.filter(
      (item) =>
        item.name.toLowerCase().includes(q) ||
        (item.designation && item.designation.toLowerCase().includes(q))
    );
  }, [attendanceItems, searchText]);

  // Fetch Daily Attendance from API
  const fetchDailyAttendance = async () => {
    try {
      setLoading(true);
      const dateStr = selectedDate.format('YYYY-MM-DD');
      const res = await jwtAxios.get(ENDPOINTS.ATTENDANCE_DAILY, {
        params: {
          date: dateStr,
        },
      });

      const result = res.data.result;
      const fetchedItems: DailyAttendanceItem[] = result?.items || [];

      setAttendanceItems(fetchedItems);

      if (result?.summary) {
        setSummary(result.summary);
      }
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch daily attendance');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchDailyAttendance();
  }, [selectedDate]);

  // Save Bulk Attendance (receives draft items from MarkAttendanceModal)
  const handleSaveAttendance = async (draftRecords: DailyAttendanceItem[]) => {
    try {
      setSaving(true);
      const dateStr = selectedDate.format('YYYY-MM-DD');
      const payload = {
        date: dateStr,
        records: draftRecords
          .filter((item) => item.status !== null)
          .map((item) => ({
            employeeId: item.employeeId,
            status: item.status!,
            remarks: item.remarks || '',
          })),
      };

      const res = await jwtAxios.post(ENDPOINTS.ATTENDANCE_BULK_SAVE, payload);
      message.success('Attendance saved successfully!');
      if (res.data.result) {
        setSummary(res.data.result);
      }
      setIsMarkModalOpen(false);
      await fetchDailyAttendance();
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to save attendance');
    } finally {
      setSaving(false);
    }
  };

  // Save Single Attendance (isolated from local table edits)
  const handleSaveSingleAttendance = async () => {
    if (!editEmployee || !editEmployee.status) return;
    try {
      setSaving(true);
      const dateStr = selectedDate.format('YYYY-MM-DD');
      
      // We only merge the single edited employee into the payload
      const updatedRecords = attendanceItems.map((item) =>
        item.employeeId === editEmployee.employeeId
          ? { ...item, status: editEmployee.status!, remarks: editEmployee.remarks || '' }
          : item
      );

      const payload = {
        date: dateStr,
        records: updatedRecords
          .filter((item) => item.status !== null)
          .map((item) => ({
            employeeId: item.employeeId,
            status: item.status!,
            remarks: item.remarks || '',
          })),
      };

      const res = await jwtAxios.post(ENDPOINTS.ATTENDANCE_BULK_SAVE, payload);
      message.success('Attendance saved successfully!');
      if (res.data.result) {
        setSummary(res.data.result);
      }
      setIsSingleEditModalOpen(false);
      fetchDailyAttendance();
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to save attendance');
    } finally {
      setSaving(false);
    }
  };

  // Fetch Monthly Attendance for All Employees Matrix
  const fetchMonthlyAttendance = async (targetMonth?: Dayjs) => {
    try {
      setMonthlyLoading(true);
      const activeMonth = targetMonth || calendarMonth;
      const year = activeMonth.year();
      const month = activeMonth.month() + 1;
      const res = await jwtAxios.get(ENDPOINTS.ATTENDANCE_MONTHLY, {
        params: {
          year,
          month,
          search: searchText.trim() || undefined,
        },
      });
      setMonthlyData(res.data.result?.employees || []);
    } catch (err: any) {
      message.error('Failed to fetch monthly attendance matrix');
    } finally {
      setMonthlyLoading(false);
    }
  };

  const handleMonthlyMonthChange = (updatedMonth: Dayjs) => {
    setCalendarMonth(updatedMonth);
    fetchMonthlyAttendance(updatedMonth);
  };

  // Fetch Single Employee Matrix & History
  const fetchSingleEmployeeMatrix = async (empId: string, monthVal: Dayjs) => {
    try {
      setSingleMatrixLoading(true);
      const year = monthVal.year();
      const month = monthVal.month() + 1;
      const res = await jwtAxios.get(ENDPOINTS.ATTENDANCE_EMPLOYEE(empId), {
        params: { year, month },
      });
      setSingleEmployeeData(res.data.result || null);
    } catch (err: any) {
      message.error('Failed to fetch single employee attendance matrix');
    } finally {
      setSingleMatrixLoading(false);
    }
  };

  const handleOpenSingleMatrix = (record: DailyAttendanceItem) => {
    setSingleEmployeeId(record.employeeId);
    setSingleEmployeeName(record.name);
    setIsSingleMatrixModalOpen(true);
    fetchSingleEmployeeMatrix(record.employeeId, singleMatrixMonth);
  };

  const handleSingleMatrixMonthChange = (updatedMonth: Dayjs) => {
    setSingleMatrixMonth(updatedMonth);
    if (singleEmployeeId) {
      fetchSingleEmployeeMatrix(singleEmployeeId, updatedMonth);
    }
  };

  const handleOpenMatrix = () => {
    setMatrixSearchText('');
    setIsMatrixModalOpen(true);
    fetchMonthlyAttendance();
  };

  const handleCloseMarkModal = () => {
    setIsMarkModalOpen(false);
  };

  const handleCloseMatrixModal = () => {
    setIsMatrixModalOpen(false);
    setMatrixSearchText('');
    setCalendarMonth(dayjs());
  };

  const handleCloseSingleMatrixModal = () => {
    setIsSingleMatrixModalOpen(false);
    setSingleMatrixMonth(dayjs());
  };

  // Unified Attendance Report Export Action
  const handleExportReport = async (config: AttendanceExportConfig) => {
    try {
      setExportLoading(true);

      // Determine default filename based on reportType & format
      const ext = config.format === 'excel' ? 'xlsx' : 'pdf';
      let defaultFileName = `Attendance_${config.reportType.toLowerCase()}.${ext}`;

      if (config.reportType === 'DAILY' && config.date) {
        defaultFileName = `Attendance_Daily_${config.date}.${ext}`;
      } else if (config.reportType === 'EMPLOYEE' && config.fromDate && config.toDate) {
        const empName = computedEmployees.find((e) => String(e.id) === String(config.employeeId))?.name || 'All_Employees';
        const cleanEmpName = empName.replace(/[^a-zA-Z0-9]/g, '_');
        defaultFileName = `${cleanEmpName}_Attendance_${config.fromDate}_to_${config.toDate}.${ext}`;
      } else if (config.reportType === 'MONTHLY_SUMMARY' && config.month && config.year) {
        const monthName = dayjs().month(config.month - 1).format('MMMM');
        defaultFileName = `Attendance_Monthly_Summary_${monthName}_${config.year}.${ext}`;
      } else if (config.reportType === 'REGISTER' && config.month && config.year) {
        const monthName = dayjs().month(config.month - 1).format('MMMM');
        defaultFileName = `Attendance_Register_${monthName}_${config.year}.${ext}`;
      } else if (config.reportType === 'ABSENT' && config.fromDate && config.toDate) {
        defaultFileName = `Absent_Employees_${config.fromDate}_to_${config.toDate}.${ext}`;
      } else if (config.reportType === 'HALF_DAY' && config.fromDate && config.toDate) {
        defaultFileName = `Half_Day_Report_${config.fromDate}_to_${config.toDate}.${ext}`;
      } else if (config.reportType === 'ATTENDANCE_SUMMARY' && config.month && config.year) {
        const monthName = dayjs().month(config.month - 1).format('MMMM');
        defaultFileName = `Attendance_Summary_${monthName}_${config.year}.${ext}`;
      }

      const endpoint = config.format === 'excel' 
        ? ENDPOINTS.ATTENDANCE_EXPORT_EXCEL 
        : ENDPOINTS.ATTENDANCE_EXPORT_PDF;

      const exportParams = {
        startDate: config.fromDate,
        endDate: config.toDate,
        employeeId: config.employeeId,
      };

      const response = await jwtAxios.get(endpoint, {
        params: exportParams,
        responseType: 'blob',
      });

      const disposition = response.headers['content-disposition'];
      if (disposition) {
        const match = disposition.match(/filename\*?=(?:UTF-8'')?"?([^"\n;]+)"?/i);
        if (match?.[1]) defaultFileName = decodeURIComponent(match[1]);
      }

      const mimeType =
        config.format === 'excel'
          ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
          : 'application/pdf';

      const blob = new Blob([response.data], { type: mimeType });
      const objectUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = objectUrl;
      link.download = defaultFileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(objectUrl);

      message.success(`${config.format.toUpperCase()} report exported successfully`);
      setIsExportModalOpen(false);
    } catch (err: any) {
      message.error(err.response?.data?.message || `Failed to export ${config.format.toUpperCase()} report`);
    } finally {
      setExportLoading(false);
    }
  };

  const isToday = selectedDate.isSame(dayjs(), 'day');
  const isYesterday = selectedDate.isSame(dayjs().subtract(1, 'day'), 'day');

  // Single Employee Edit Action
  const handleOpenEditSingle = (record: DailyAttendanceItem) => {
    const newStatus = record.status || 'PRESENT';
    setEditEmployee({ ...record, status: newStatus });
    setIsSingleEditModalOpen(true);
  };

  // Main Display Table Columns
  const columns = [
    {
      title: 'Employee Name',
      dataIndex: 'name',
      key: 'name',
      width: 200,
      render: (name: string) => <span className="font-bold text-slate-900 text-xs">{name}</span>,
    },
    {
      title: 'Designation',
      dataIndex: 'designation',
      key: 'designation',
      width: 160,
      render: (desig: string) => (
        <span className="text-xs text-slate-600 font-medium">
          {desig || 'Staff'}
        </span>
      ),
    },
    {
      title: 'Attendance',
      dataIndex: 'status',
      key: 'status',
      width: 150,
      render: (status: AttendanceStatusType | null) => {
        if (status === 'PRESENT') {
          return <Tag color="green" className="font-extrabold px-3 py-0.5 rounded-md">Present (P)</Tag>;
        }
        if (status === 'ABSENT') {
          return <Tag color="red" className="font-extrabold px-3 py-0.5 rounded-md">Absent (A)</Tag>;
        }
        if (status === 'HALF_DAY') {
          return <Tag color="gold" className="font-extrabold px-3 py-0.5 rounded-md">Half Day (H)</Tag>;
        }
        return <Tag color="default" className="font-semibold px-3 py-0.5 rounded-md text-slate-400">Not Marked</Tag>;
      },
    },
    {
      title: 'Remarks',
      dataIndex: 'remarks',
      key: 'remarks',
      width: 220,
      render: (remarks: string) => {
        if (!remarks || !remarks.trim()) {
          return <span className="text-slate-400 text-xs italic">-</span>;
        }
        return (
          <Popover
            content={<div className="max-w-xs text-xs text-slate-800 wrap-break-word">{remarks}</div>}
            title="Remarks"
          >
            <span className="text-slate-700 font-medium text-xs truncate max-w-50 inline-block cursor-pointer hover:text-blue-600">
              {remarks}
            </span>
          </Popover>
        );
      },
    },
    {
      title: 'Actions',
      key: 'actions',
      width: 120,
      render: (_: any, record: DailyAttendanceItem) => (
        <Space>
          <Popover content="Edit Attendance">
            <Button
              type="link"
              icon={<EditOutlined />}
              onClick={() => handleOpenEditSingle(record)}
            />
          </Popover>
          <Popover content="Single Calendar Matrix">
            <Button
              type="link"
              icon={<CalendarOutlined className="text-purple-600" />}
              onClick={() => handleOpenSingleMatrix(record)}
            />
          </Popover>
        </Space>
      ),
    },
  ];

  return (
    <div>
      <Spin spinning={loading}>
        <AppContainer
          title="Attendance Management"
          headerAction={
            <Space wrap>
              <Button
                type="primary"
                icon={<FormOutlined />}
                onClick={() => setIsMarkModalOpen(true)}
                className="bg-emerald-600 hover:bg-emerald-700 border-none"
              >
                Mark Attendance
              </Button>

              <Button
                icon={<TableOutlined />}
                onClick={handleOpenMatrix}
              >
                Matrix View
              </Button>

              <Button
                icon={<DownloadOutlined />}
                onClick={() => setIsExportModalOpen(true)}
                style={{ color: '#16a34a', borderColor: '#16a34a' }}
              >
                Export Report
              </Button>
            </Space>
          }
        >
          {/* Summary Cards */}
          <Row gutter={[16, 16]} style={{ marginBottom: 20 }}>
            <Col xs={24} sm={12} md={6}>
              <SummaryCard
                label="Total"
                value={attendanceItems.length}
                icon={<TeamOutlined />}
                color="#2563eb"
                showCurrency={false}
              />
            </Col>
            <Col xs={24} sm={12} md={6}>
              <SummaryCard
                label="Present"
                value={summary.present}
                icon={<CheckCircleOutlined />}
                color="#16a34a"
                showCurrency={false}
              />
            </Col>
            <Col xs={24} sm={12} md={6}>
              <SummaryCard
                label="Absent"
                value={summary.absent}
                icon={<CloseCircleOutlined />}
                color="#dc2626"
                showCurrency={false}
              />
            </Col>
            <Col xs={24} sm={12} md={6}>
              <SummaryCard
                label="Half Day"
                value={summary.halfDay}
                icon={<ClockCircleOutlined />}
                color="#d97706"
                showCurrency={false}
              />
            </Col>
          </Row>

          {/* Search and Date Filter Bar */}
          <div className="flex flex-wrap justify-between items-center mb-4 pb-4 border-b border-gray-200 gap-4">
            <Space wrap>
              {/* Quick Date Pills */}
              <div className="inline-flex bg-slate-100 p-1 rounded-lg border border-slate-200 gap-1">
                <button
                  type="button"
                  onClick={() => setSelectedDate(dayjs())}
                  className={`px-3 py-1 rounded-md text-xs font-semibold transition-all duration-150 cursor-pointer ${isToday
                    ? 'bg-blue-600 text-white shadow-2xs font-bold'
                    : 'text-slate-600 hover:text-slate-900 hover:bg-slate-200/60'
                    }`}
                >
                  Today
                </button>
                <button
                  type="button"
                  onClick={() => setSelectedDate(dayjs().subtract(1, 'day'))}
                  className={`px-3 py-1 rounded-md text-xs font-semibold transition-all duration-150 cursor-pointer ${isYesterday
                    ? 'bg-blue-600 text-white shadow-2xs font-bold'
                    : 'text-slate-600 hover:text-slate-900 hover:bg-slate-200/60'
                    }`}
                >
                  Yesterday
                </button>
              </div>

              <DatePicker
                value={selectedDate}
                onChange={(d) => d && setSelectedDate(d)}
                format="DD MMM YYYY"
                disabledDate={(current) => current ? current.isAfter(dayjs().endOf('day')) : false}
                allowClear={false}
                style={{ width: 150 }}
              />

              <Input.Search
                placeholder="Search employee by name or designation..."
                value={searchText}
                onChange={(e) => setSearchText(e.target.value)}
                onSearch={(val) => setSearchText(val)}
                allowClear
                style={{ width: 290 }}
              />
            </Space>

            <Tag color="blue" className="font-bold text-xs px-3 py-1 rounded-md">
              Date: {selectedDate.format('DD MMM YYYY')}
            </Tag>
          </div>

          {/* AntD Main Display Table */}
          <Table
            rowKey="employeeId"
            columns={columns}
            dataSource={filteredDailyAttendance}
            loading={loading}
            scroll={{ x: 'max-content', y: 450 }}
            pagination={{
              pageSize: 10,
              showSizeChanger: true,
            }}
          />
        </AppContainer>
      </Spin>

      {/* ── MODAL 1: BULK ATTENDANCE MARKING MODAL ────────── */}
      <MarkAttendanceModal
        open={isMarkModalOpen}
        onCancel={handleCloseMarkModal}
        selectedDate={selectedDate}
        attendanceItems={attendanceItems}
        loading={loading}
        saving={saving}
        onSaveAttendance={handleSaveAttendance}
      />

      {/* ── MODAL 2: ALL EMPLOYEES MONTHLY ATTENDANCE MATRIX VIEW ────────── */}
      <MonthlyMatrixModal
        open={isMatrixModalOpen}
        onCancel={handleCloseMatrixModal}
        calendarMonth={calendarMonth}
        monthlyData={filteredMonthlyData}
        monthlyLoading={monthlyLoading}
        searchText={matrixSearchText}
        onSearchChange={setMatrixSearchText}
        onFetchMonthlyAttendance={() => fetchMonthlyAttendance()}
        onMonthChange={handleMonthlyMonthChange}
      />

      {/* ── MODAL 3: SINGLE EMPLOYEE ATTENDANCE CALENDAR MATRIX ────────── */}
      <SingleEmployeeMatrixModal
        open={isSingleMatrixModalOpen}
        onCancel={handleCloseSingleMatrixModal}
        singleEmployeeName={singleEmployeeName}
        singleEmployeeData={singleEmployeeData}
        singleMatrixLoading={singleMatrixLoading}
        singleMatrixMonth={singleMatrixMonth}
        onMonthChange={handleSingleMatrixMonthChange}
      />

      {/* ── MODAL 4: ATTENDANCE REPORT EXPORT MODAL ────────── */}
      <ExportAttendanceModal
        open={isExportModalOpen}
        onCancel={() => setIsExportModalOpen(false)}
        onExport={handleExportReport}
        employees={computedEmployees}
        exportLoading={exportLoading}
      />

      {/* ── MODAL 5: EDIT SINGLE EMPLOYEE ATTENDANCE ────────── */}
      <EditSingleAttendanceModal
        open={isSingleEditModalOpen}
        onCancel={() => setIsSingleEditModalOpen(false)}
        editEmployee={editEmployee}
        saving={saving}
        setEditEmployee={setEditEmployee}
        onSaveAttendance={handleSaveSingleAttendance}
      />
    </div>
  );
};

export default Attendance;
