import React, { useEffect, useMemo } from 'react';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import {
  DataTable,
  type DataTableHeader,
  Table,
  TableCell,
  TableContainer,
  TableBody,
  TableHead,
  TableHeader,
  TableRow,
} from '@carbon/react';
import { PatientChartPagination } from '@openmrs/esm-patient-common-lib';
import { formatDatetime, parseDate, useLayoutType, usePagination } from '@openmrs/esm-framework';
import { type Appointment } from '../types';
import { PatientAppointmentsActionMenu } from './patient-appointments-action-menu.component';
import styles from './patient-appointments-table.scss';

const pageSize = 10;

interface AppointmentTableProps {
  patientAppointments: Array<Appointment>;
  switchedView: boolean;
  setSwitchedView: (value: boolean) => void;
  patientUuid: string;
}

// Updated type to handle the actual API response structure
type AppointmentWithExtras = Appointment & {
  reason?: {
    person: string;
    concept: string;
    value:
      | string
      | {
          uuid: string;
          display: string;
          links: Array<any>;
        };
    obsDatetime: string;
  };
  note?: string;
  location?: { display?: string; name?: string };
  appointmentDate?: string; // This is the field the API actually uses
  appointmentId?: number;
};

const PatientAppointmentsTable: React.FC<AppointmentTableProps> = ({
  patientAppointments,
  patientUuid,
  switchedView,
  setSwitchedView,
}) => {
  const { t } = useTranslation();

  // FIXED: Create filtered appointments list to exclude cancelled/retired appointments
  const filteredAppointments = useMemo(
    () => patientAppointments.filter((a) => a.status !== 'Cancelled' && a.status !== 'RETIRED'),
    [patientAppointments],
  );

  const { results: paginatedAppointments, currentPage, goTo } = usePagination(filteredAppointments, pageSize);

  const isTablet = useLayoutType() === 'tablet';

  useEffect(() => {
    if (switchedView && currentPage !== 1) {
      goTo(1);
    }
  }, [switchedView, goTo, currentPage]);

  const tableHeaders: Array<typeof DataTableHeader> = useMemo(
    () => [
      { key: 'date', header: t('date', 'Date') },
      { key: 'reason', header: t('reason', 'Reason') },
      { key: 'service', header: t('service', 'Service') },
      { key: 'location', header: t('location', 'Location') },
      { key: 'notes', header: t('notes', 'Notes') },
    ],
    [t],
  );

  const tableRows = useMemo(
    () =>
      (paginatedAppointments as AppointmentWithExtras[])?.map((appointment) => {
        // Helper function to safely convert any value to string
        const safeStringify = (value: any): string => {
          if (value === null || value === undefined) {
            return '——';
          }
          if (typeof value === 'string') {
            return value;
          }
          if (typeof value === 'number') {
            return value.toString();
          }
          if (typeof value === 'object') {
            if (value.display) {
              return value.display;
            }
            if (value.name) {
              return value.name;
            }
            return '——';
          }
          return '——';
        };

        // Handle reason display
        let reasonValue = '——';
        if (appointment.reason?.value) {
          if (typeof appointment.reason.value === 'string') {
            reasonValue = appointment.reason.value;
          } else if (typeof appointment.reason.value === 'object' && appointment.reason.value.display) {
            reasonValue = appointment.reason.value.display;
          }
        } else if (appointment.comments) {
          reasonValue = safeStringify(appointment.comments);
        } else if (appointment.note) {
          reasonValue = safeStringify(appointment.note);
        }

        // FIXED: Handle notes display properly - only show actual notes, not fallback to reason
        const getNotesValue = (appointment: AppointmentWithExtras): string => {
          // Check for actual notes in the note field
          const noteValue = appointment.note;
          if (noteValue && typeof noteValue === 'string' && noteValue.trim() !== '') {
            return noteValue.trim();
          }

          // Check for actual notes in the comments field
          const commentsValue = appointment.comments;
          if (commentsValue && typeof commentsValue === 'string' && commentsValue.trim() !== '') {
            // Make sure comments is not the same as the reason to avoid duplication
            const commentsStr = commentsValue.trim();
            if (commentsStr !== reasonValue) {
              return commentsStr;
            }
          }

          // If no actual notes, return "——"
          return '——';
        };

        // Use OpenMRS framework date formatting for consistent timezone handling
        const formatAppointmentDateTime = (appointment: AppointmentWithExtras): string => {
          try {
            // Use appointmentDate field first, then fall back to startDateTime
            const dateToFormat = appointment.appointmentDate || appointment.startDateTime;

            if (!dateToFormat) {
              console.warn('No date field found in appointment:', appointment);
              return '——';
            }

            // Parse the date using OpenMRS parseDate utility
            // This handles various formats including those with/without timezone info
            const parsedDate = parseDate(dateToFormat);

            if (!parsedDate) {
              console.warn('Failed to parse appointment date:', dateToFormat);
              return '——';
            }

            // Format using OpenMRS framework's date formatting functions
            // This ensures consistent timezone handling and locale-aware display
            return formatDatetime(parsedDate, { mode: 'wide' });
          } catch (error) {
            console.error('Error formatting appointment date:', error);
            return '——';
          }
        };

        return {
          id: appointment.uuid || appointment.appointmentId,
          date: formatAppointmentDateTime(appointment),
          reason: reasonValue,
          service: safeStringify(appointment.service?.name) || '——',
          location: safeStringify(appointment.location?.display) || safeStringify(appointment.location?.name) || '——',
          notes: getNotesValue(appointment),
        };
      }),
    [paginatedAppointments],
  );

  return (
    <div>
      <DataTable rows={tableRows} headers={tableHeaders} isSortable size={isTablet ? 'lg' : 'sm'} useZebraStyles>
        {({ rows, headers, getHeaderProps, getTableProps }) => (
          <TableContainer>
            <Table className={styles.table} {...getTableProps()}>
              <TableHead>
                <TableRow>
                  {headers.map((header) => (
                    <TableHeader
                      key={header.key}
                      className={classNames(styles.productiveHeading01, styles.text02)}
                      {...getHeaderProps({
                        header,
                        isSortable: header.isSortable,
                      })}
                    >
                      {header.header?.content ?? header.header}
                    </TableHeader>
                  ))}
                  <TableHeader />
                </TableRow>
              </TableHead>
              <TableBody>
                {rows.map((row, i) => (
                  <TableRow key={row.id}>
                    {row.cells.map((cell) => (
                      <TableCell key={cell.id}>
                        {(() => {
                          const value = cell.value?.content ?? cell.value;
                          if (typeof value === 'object' && value !== null) {
                            if (value.display) {
                              return value.display;
                            }
                            if (value.name) {
                              return value.name;
                            }
                            return '——';
                          }
                          return value || '——';
                        })()}
                      </TableCell>
                    ))}
                    <TableCell className="cds--table-column-menu">
                      <PatientAppointmentsActionMenu appointment={paginatedAppointments[i]} patientUuid={patientUuid} />
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        )}
      </DataTable>
      <PatientChartPagination
        currentItems={paginatedAppointments.length}
        totalItems={filteredAppointments.length}
        onPageNumberChange={({ page }) => {
          setSwitchedView(false);
          goTo(page);
        }}
        pageNumber={currentPage}
        pageSize={pageSize}
      />
    </div>
  );
};

export default PatientAppointmentsTable;
