import { Calendar, Loader2, Save, X } from 'lucide-react';
import { generatePath, Link } from 'react-router-dom';

import { getDraftAttendancePercentage } from '@/business/campus-attendance/selectors';
import type {
  CampusAttendancePageActions,
  CampusAttendancePageState,
} from '@/components/campus-attendance/types';
import type { StaffAttendanceStatus } from '@/shared/types/staffAttendance';
import { percentageTextClass } from '@/components/campus-attendance/styles';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useScopeContext } from '@/contexts/scope-context';
import { APP_ROUTE_PATHS } from '@/shared/constants/routes';
import type { ActiveTenant } from '@/shared/types/scope';

type CampusAttendanceEntryFormProps = {
  state: CampusAttendancePageState;
  actions: CampusAttendancePageActions;
};

type AttendanceRouteState = {
  readonly __scope: ActiveTenant | null;
};

const STAFF_ATTENDANCE_STATUS_OPTIONS: readonly {
  value: StaffAttendanceStatus;
  label: string;
}[] = [
  { value: 'present', label: 'Present' },
  { value: 'late', label: 'Late' },
  { value: 'absent', label: 'Absent' },
];

function formatRoleName(role: string | null): string {
  if (!role) {
    return 'Staff';
  }

  return role
    .split('_')
    .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
    .join(' ');
}

export function CampusAttendanceEntryForm({ state, actions }: CampusAttendanceEntryFormProps) {
  const { selectedTenant } = useScopeContext();
  const {
    campusInfo,
    entryDraft,
    entryError,
    saving,
    scopeModel,
    staffEntryDraft,
    staffEntryError,
    officeStaffUsers,
    staffAttendanceStatuses,
    studentRollupRows,
    attendanceStudents,
    studentAttendanceStatuses,
    attendanceStudentsLoading,
  } = state;
  const draftPercentage = getDraftAttendancePercentage(entryDraft);
  const showStudentRollup = scopeModel.mode !== 'campus';
  const entryTargetLabel = showStudentRollup
    ? scopeModel.reportLabel
    : scopeModel.tenantName || campusInfo?.fullName || 'Current Scope';
  const hasStudentRoster = attendanceStudents.length > 0;
  const staffAttendanceLabel = scopeModel.tier === 'class'
    ? 'Classroom Staff Attendance'
    : scopeModel.mode === 'campus'
      ? 'Campus Staff Attendance'
      : 'Office Staff Attendance';
  const staffAttendanceDescription = scopeModel.tier === 'class'
    ? 'Record attendance for classroom staff.'
    : scopeModel.mode === 'campus'
    ? 'Record attendance for campus staff.'
    : `Record attendance for ${scopeModel.reportLabel.toLowerCase()} office staff.`;
  const noStudentRosterText = scopeModel.tier === 'class'
    ? 'No students are available for this classroom.'
    : 'No students are available for this campus.';
  const scopeRouteState: AttendanceRouteState = { __scope: selectedTenant };
  const studentAttendanceSaveDisabled = attendanceStudentsLoading
    || (showStudentRollup
      ? studentRollupRows.length === 0
      : !hasStudentRoster && (!entryDraft.enrolled || !entryDraft.present || !entryDraft.absent));

  return (
    <div className="bg-slate-800/60 backdrop-blur-sm rounded-2xl border border-orange-500/20 p-6">
      <div className="flex items-center justify-between mb-5">
        <h3 className="font-semibold text-white flex items-center gap-2">
          <Calendar size={18} className="text-orange-400" />
          Enter Attendance for {entryTargetLabel}
        </h3>
        <button
          type="button"
          onClick={() => actions.setShowEntryForm(false)}
          className="text-slate-400 hover:text-white transition-colors"
          aria-label="Close attendance entry form"
        >
          <X size={18} />
        </button>
      </div>
      {showStudentRollup && (
        <div className="mb-5">
          <h4 className="text-sm font-semibold text-slate-200">Student Attendance Rollup</h4>
          <p className="mt-1 text-xs text-slate-400">
            Review and edit totals collected from campuses inside this {scopeModel.mode}.
          </p>
        </div>
      )}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        <AttendanceEntryInput label="Date" type="date" value={entryDraft.date} onChange={(value) => actions.updateEntryDraft({ date: value })} />
        {!showStudentRollup && (
          <AttendanceEntryInput label="Notes (optional)" type="text" value={entryDraft.notes} placeholder="Any notes..." onChange={(value) => actions.updateEntryDraft({ notes: value })} />
        )}
      </div>
      {showStudentRollup ? (
        <>
          <StudentRollupTable
            className="mt-4"
            rows={studentRollupRows}
            routeState={scopeRouteState}
            onChange={actions.updateStudentRollupDraft}
          />
        </>
      ) : attendanceStudentsLoading ? (
        <div className="mt-4 flex items-center gap-2 rounded-xl border border-slate-700/70 bg-slate-900/40 px-4 py-3 text-sm text-slate-400">
          <Loader2 size={16} className="animate-spin" />
          Loading student roster...
        </div>
      ) : hasStudentRoster ? (
        <AttendanceRosterTable
          className="mt-4"
          users={attendanceStudents}
          statuses={studentAttendanceStatuses}
          emptyText={noStudentRosterText}
          onStatusChange={actions.updateStudentAttendanceStatus}
        />
      ) : (
        <div className="mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
          <AttendanceEntryInput label="Total Enrolled" value={entryDraft.enrolled} placeholder="e.g. 45" onChange={(value) => actions.updateEntryDraft({ enrolled: value })} />
          <AttendanceEntryInput label="Total Present" value={entryDraft.present} placeholder="e.g. 42" onChange={(value) => actions.updateEntryDraft({ present: value })} />
          <AttendanceEntryInput label="Total Absent" value={entryDraft.absent} placeholder="e.g. 2" onChange={(value) => actions.updateEntryDraft({ absent: value })} />
          <AttendanceEntryInput label="Total Tardy" value={entryDraft.tardy} placeholder="e.g. 1" onChange={(value) => actions.updateEntryDraft({ tardy: value })} />
        </div>
      )}
      {!hasStudentRoster && draftPercentage !== null && (
        <div className="mt-4 p-3 rounded-xl bg-slate-700/30 border border-slate-600/30">
          <p className="text-sm text-slate-300">
            Calculated Attendance:{' '}
            <span className={`font-bold text-lg ${percentageTextClass(draftPercentage)}`}>
              {draftPercentage.toFixed(1)}%
            </span>
          </p>
        </div>
      )}
      {entryError && <p className="mt-3 text-sm text-red-300">{entryError}</p>}
      <div className="mt-6 border-t border-slate-700/70 pt-6">
        <div className="mb-4">
          <h4 className="text-sm font-semibold text-slate-200">{staffAttendanceLabel}</h4>
          <p className="mt-1 text-xs text-slate-400">
            {staffAttendanceDescription}
          </p>
        </div>
        {officeStaffUsers.length > 0 ? (
          <>
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
              <AttendanceEntryInput
                label="Date"
                type="date"
                value={staffEntryDraft.date}
                onChange={(value) => actions.updateStaffEntryDraft({ date: value })}
              />
              <div className="lg:col-span-4">
                <AttendanceEntryInput
                  label="Notes (optional)"
                  type="text"
                  value={staffEntryDraft.note}
                  placeholder="Any notes..."
                  onChange={(value) => actions.updateStaffEntryDraft({ note: value })}
                />
              </div>
            </div>
            <AttendanceRosterTable
              className="mt-4"
              users={officeStaffUsers}
              statuses={staffAttendanceStatuses}
              emptyText="No staff are available for this scope."
              onStatusChange={actions.updateStaffAttendanceStatus}
            />
            {staffEntryError && <p className="mt-3 text-sm text-red-300">{staffEntryError}</p>}
          </>
        ) : (
          <div className="rounded-xl border border-slate-700/70 bg-slate-900/40 px-4 py-3 text-sm text-slate-400">
            No staff are available for this scope.
          </div>
        )}
      </div>
      <div className="mt-6 flex justify-end border-t border-slate-700/70 pt-6">
        <Button
          type="button"
          onClick={actions.handleSubmitAttendanceForm}
          disabled={saving || studentAttendanceSaveDisabled}
          loading={saving}
          loadingLabel="Saving..."
          leadingIcon={<Save size={14} />}
          className="flex items-center gap-2 px-6 py-2.5 bg-gradient-to-r from-orange-500 to-amber-500 text-white rounded-xl font-medium text-sm hover:shadow-lg transition-all disabled:opacity-50"
        >
          Save Attendance
        </Button>
      </div>
    </div>
  );
}

type StudentRollupTableProps = {
  rows: CampusAttendancePageState['studentRollupRows'];
  routeState: AttendanceRouteState;
  className?: string;
  onChange: CampusAttendancePageActions['updateStudentRollupDraft'];
};

function StudentRollupTable({
  rows,
  routeState,
  className,
  onChange,
}: StudentRollupTableProps) {
  if (rows.length === 0) {
    return (
      <div className={className}>
        <div className="rounded-xl border border-slate-700/70 bg-slate-900/40 px-4 py-3 text-sm text-slate-400">
          No campuses are available in this scope.
        </div>
      </div>
    );
  }

  const totals = rows.reduce(
    (currentTotals, row) => ({
      enrolled: currentTotals.enrolled + (Number.parseInt(row.enrolled, 10) || 0),
      present: currentTotals.present + (Number.parseInt(row.present, 10) || 0),
      absent: currentTotals.absent + (Number.parseInt(row.absent, 10) || 0),
      tardy: currentTotals.tardy + (Number.parseInt(row.tardy, 10) || 0),
    }),
    { enrolled: 0, present: 0, absent: 0, tardy: 0 },
  );
  const hasAnyValue = rows.some((row) => row.enrolled || row.present || row.absent || row.tardy);

  return (
    <div className={className}>
      <div className="overflow-x-auto rounded-xl border border-slate-700/70 bg-slate-900/30">
        <table className="w-full min-w-[900px] text-left text-sm">
          <thead className="bg-slate-900/70 text-xs uppercase text-slate-400">
            <tr>
              <th className="px-4 py-3 font-semibold">Campus</th>
              <th className="w-32 px-3 py-3 font-semibold">Enrolled</th>
              <th className="w-32 px-3 py-3 font-semibold">Present</th>
              <th className="w-32 px-3 py-3 font-semibold">Absent</th>
              <th className="w-32 px-3 py-3 font-semibold">Tardy</th>
              <th className="px-3 py-3 font-semibold">Notes</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-slate-800/80">
            {rows.map((row) => (
              <tr key={row.campusId} className="text-slate-200">
                <td className="px-4 py-3">
                  <Link
                    to={generatePath(APP_ROUTE_PATHS.attendanceDetails, { level: 'campus', tenantId: row.campusId })}
                    state={routeState}
                    className="text-left font-medium text-white transition-colors hover:text-orange-300 focus:outline-none focus:ring-2 focus:ring-orange-500/50 rounded"
                  >
                    {row.campusName}
                  </Link>
                  <div className="mt-1 text-xs text-slate-500">
                    {row.hasRecordedData ? 'Recorded for selected date' : 'No child data yet'}
                  </div>
                </td>
                <StudentRollupInput
                  label={`Enrolled for ${row.campusName}`}
                  value={row.enrolled}
                  onChange={(value) => onChange(row.campusId, { enrolled: value })}
                />
                <StudentRollupInput
                  label={`Present for ${row.campusName}`}
                  value={row.present}
                  onChange={(value) => onChange(row.campusId, { present: value })}
                />
                <StudentRollupInput
                  label={`Absent for ${row.campusName}`}
                  value={row.absent}
                  onChange={(value) => onChange(row.campusId, { absent: value })}
                />
                <StudentRollupInput
                  label={`Tardy for ${row.campusName}`}
                  value={row.tardy}
                  onChange={(value) => onChange(row.campusId, { tardy: value })}
                />
                <td className="px-3 py-3">
                  <Input
                    type="text"
                    value={row.notes}
                    onChange={(event) => onChange(row.campusId, { notes: event.target.value })}
                    aria-label={`Notes for ${row.campusName}`}
                    placeholder="Any notes..."
                    className="w-full px-3 py-2 bg-slate-800/80 border border-slate-600/50 rounded-lg text-sm text-white focus:ring-2 focus:ring-orange-500/50 outline-none placeholder:text-slate-500"
                  />
                </td>
              </tr>
            ))}
          </tbody>
          <tfoot className="border-t border-slate-700/80 bg-slate-900/50 text-slate-200">
            <tr>
              <td className="px-4 py-3 font-semibold">Current totals</td>
              <td className="px-3 py-3 font-semibold">{hasAnyValue ? totals.enrolled : ''}</td>
              <td className="px-3 py-3 font-semibold">{hasAnyValue ? totals.present : ''}</td>
              <td className="px-3 py-3 font-semibold">{hasAnyValue ? totals.absent : ''}</td>
              <td className="px-3 py-3 font-semibold">{hasAnyValue ? totals.tardy : ''}</td>
              <td className="px-3 py-3 text-xs text-slate-500">Saved per campus</td>
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
  );
}

type StudentRollupInputProps = {
  label: string;
  value: string;
  onChange: (value: string) => void;
};

function StudentRollupInput({ label, value, onChange }: StudentRollupInputProps) {
  return (
    <td className="px-3 py-3">
      <Input
        type="number"
        min="0"
        value={value}
        onChange={(event) => onChange(event.target.value)}
        aria-label={label}
        className="w-full px-3 py-2 bg-slate-800/80 border border-slate-600/50 rounded-lg text-sm text-white focus:ring-2 focus:ring-orange-500/50 outline-none placeholder:text-slate-500"
      />
    </td>
  );
}

type AttendanceRosterTableProps = {
  users: readonly {
    id: string;
    name: string;
    role: string | null;
  }[];
  statuses: Readonly<Record<string, StaffAttendanceStatus>>;
  emptyText: string;
  className?: string;
  onStatusChange: (userId: string, status: StaffAttendanceStatus) => void;
};

function AttendanceRosterTable({
  users,
  statuses,
  emptyText,
  className,
  onStatusChange,
}: AttendanceRosterTableProps) {
  if (users.length === 0) {
    return (
      <div className={className}>
        <div className="rounded-xl border border-slate-700/70 bg-slate-900/40 px-4 py-3 text-sm text-slate-400">
          {emptyText}
        </div>
      </div>
    );
  }

  const totals = users.reduce(
    (currentTotals, user) => {
      const status = statuses[user.id] ?? 'present';
      return {
        enrolled: currentTotals.enrolled + 1,
        present: currentTotals.present + (status === 'absent' ? 0 : 1),
        late: currentTotals.late + (status === 'late' ? 1 : 0),
        absent: currentTotals.absent + (status === 'absent' ? 1 : 0),
      };
    },
    { enrolled: 0, present: 0, late: 0, absent: 0 },
  );

  return (
    <div className={className}>
      <div className="overflow-hidden rounded-xl border border-slate-700/70 bg-slate-900/30">
        <table className="w-full min-w-[640px] text-left text-sm">
          <thead className="bg-slate-900/70 text-xs uppercase text-slate-400">
            <tr>
              <th className="px-4 py-3 font-semibold">Name</th>
              <th className="px-4 py-3 font-semibold">Type / role</th>
              {STAFF_ATTENDANCE_STATUS_OPTIONS.map((option) => (
                <th key={option.value} className="w-28 px-4 py-3 text-center font-semibold">
                  {option.label}
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="divide-y divide-slate-800/80">
            {users.map((user) => {
              const currentStatus = statuses[user.id] ?? 'present';
              return (
                <tr key={user.id} className="text-slate-200">
                  <td className="px-4 py-3 font-medium">{user.name}</td>
                  <td className="px-4 py-3 text-slate-400">{formatRoleName(user.role)}</td>
                  {STAFF_ATTENDANCE_STATUS_OPTIONS.map((option) => (
                    <td key={option.value} className="px-4 py-3 text-center">
                      <input
                        type="checkbox"
                        checked={currentStatus === option.value}
                        onChange={() => onStatusChange(user.id, option.value)}
                        aria-label={`${option.label} for ${user.name}`}
                        className="h-4 w-4 rounded border-slate-500 bg-slate-800 text-orange-500 focus:ring-orange-500"
                      />
                    </td>
                  ))}
                </tr>
              );
            })}
          </tbody>
          <tfoot className="border-t border-slate-700/80 bg-slate-900/50 text-slate-200">
            <tr>
              <td className="px-4 py-3 font-semibold">Totals</td>
              <td className="px-4 py-3 text-xs text-slate-400">
                Enrolled: <span className="font-semibold text-slate-200">{totals.enrolled}</span>
              </td>
              <td className="px-4 py-3 text-center font-semibold">{totals.present}</td>
              <td className="px-4 py-3 text-center font-semibold">{totals.late}</td>
              <td className="px-4 py-3 text-center font-semibold">{totals.absent}</td>
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
  );
}

type AttendanceEntryInputProps = {
  label: string;
  value: string;
  onChange: (value: string) => void;
  type?: 'date' | 'number' | 'text';
  placeholder?: string;
};

function AttendanceEntryInput({
  label,
  value,
  onChange,
  type = 'number',
  placeholder,
}: AttendanceEntryInputProps) {
  return (
    <div>
      <label className="block text-xs text-slate-400 mb-1.5 font-medium">{label}</label>
      <Input
        type={type}
        value={value}
        onChange={(event) => onChange(event.target.value)}
        placeholder={placeholder}
        className="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600/50 rounded-xl text-sm text-white focus:ring-2 focus:ring-orange-500/50 outline-none placeholder:text-slate-500"
      />
    </div>
  );
}
