"use client";

import { useEffect, useState } from "react";
import type { StudyFieldMatrixGrade, StudyFieldMatrixStage } from "@/lib/types";

function gradeNeedsFieldChoice(grade: StudyFieldMatrixGrade): boolean {
  return grade.study_fields.length > 1;
}

export function GradeLevelTree({
  stages,
  selected,
  onChange,
  gradeStudyFields,
  onGradeStudyFieldsChange,
  description = "روی نام پایه کلیک کنید تا رشته‌ها باز شوند و بتوانید فقط بعضی را تیک بزنید. تیک خود پایه یا مقطع، همهٔ زیرمجموعه‌ها را یکجا انتخاب می‌کند.",
  readOnlyGrades = false,
}: {
  stages: StudyFieldMatrixStage[];
  selected: number[];
  onChange: (ids: number[]) => void;
  gradeStudyFields?: Record<number, number[]>;
  onGradeStudyFieldsChange?: (value: Record<number, number[]>) => void;
  description?: string;
  readOnlyGrades?: boolean;
}) {
  const fieldSelections = gradeStudyFields ?? {};
  const [expandedGrades, setExpandedGrades] = useState<number[]>([]);

  useEffect(() => {
    setExpandedGrades((prev) => {
      const extra = selected.filter((id) => !prev.includes(id));
      if (extra.length === 0) return prev;
      return [...prev, ...extra];
    });
  }, [selected]);

  const toggleExpanded = (gradeId: number) => {
    setExpandedGrades((prev) =>
      prev.includes(gradeId) ? prev.filter((id) => id !== gradeId) : [...prev, gradeId],
    );
  };

  const setGradeFields = (gradeId: number, fieldIds: number[]) => {
    if (!onGradeStudyFieldsChange) return;
    onGradeStudyFieldsChange({ ...fieldSelections, [gradeId]: fieldIds });
  };

  const clearGradeFields = (gradeId: number) => {
    if (!onGradeStudyFieldsChange) return;
    const next = { ...fieldSelections };
    delete next[gradeId];
    onGradeStudyFieldsChange(next);
  };

  const toggleGrade = (grade: StudyFieldMatrixGrade) => {
    if (readOnlyGrades) return;
    const orgFieldIds = grade.study_fields.map((f) => f.id);
    const isSelected = selected.includes(grade.id);
    const selectedFields = fieldSelections[grade.id] ?? [];
    const needsChoice = gradeNeedsFieldChoice(grade);
    const allFieldsSelected =
      orgFieldIds.length > 0 && orgFieldIds.every((id) => selectedFields.includes(id));

    if (!isSelected) {
      onChange([...selected, grade.id]);
      if (orgFieldIds.length > 0) {
        setGradeFields(grade.id, [...orgFieldIds]);
      }
      if (needsChoice && !expandedGrades.includes(grade.id)) {
        setExpandedGrades((prev) => [...prev, grade.id]);
      }
      return;
    }

    if (needsChoice && !allFieldsSelected) {
      setGradeFields(grade.id, [...orgFieldIds]);
      return;
    }

    onChange(selected.filter((x) => x !== grade.id));
    clearGradeFields(grade.id);
  };

  const toggleStage = (stage: StudyFieldMatrixStage) => {
    if (readOnlyGrades) return;
    const grades = stage.grade_levels ?? [];
    const gradeIds = grades.map((g) => g.id);
    const allGradesSelected =
      gradeIds.length > 0 && gradeIds.every((id) => selected.includes(id));
    const allFieldsComplete = grades.every((grade) => {
      if (!gradeNeedsFieldChoice(grade)) return true;
      const ids = fieldSelections[grade.id] ?? [];
      return grade.study_fields.every((f) => ids.includes(f.id));
    });
    const fullySelected = allGradesSelected && allFieldsComplete;

    if (fullySelected) {
      onChange(selected.filter((id) => !gradeIds.includes(id)));
      if (onGradeStudyFieldsChange) {
        const next = { ...fieldSelections };
        gradeIds.forEach((id) => delete next[id]);
        onGradeStudyFieldsChange(next);
      }
      return;
    }

    onChange([...new Set([...selected, ...gradeIds])]);
    if (onGradeStudyFieldsChange) {
      const next = { ...fieldSelections };
      grades.forEach((grade) => {
        if (grade.study_fields.length > 0) {
          next[grade.id] = grade.study_fields.map((f) => f.id);
        }
      });
      onGradeStudyFieldsChange(next);
    }
    setExpandedGrades((prev) => [...new Set([...prev, ...gradeIds])]);
  };

  const toggleField = (grade: StudyFieldMatrixGrade, fieldId: number) => {
    if (!onGradeStudyFieldsChange) return;
    const orgFieldIds = grade.study_fields.map((f) => f.id);
    const current = fieldSelections[grade.id] ?? [];
    const nextIds = current.includes(fieldId)
      ? current.filter((id) => id !== fieldId)
      : [...current, fieldId];

    if (nextIds.length === 0) {
      onChange(selected.filter((id) => id !== grade.id));
      clearGradeFields(grade.id);
      return;
    }

    setGradeFields(grade.id, nextIds);

    if (!selected.includes(grade.id)) {
      onChange([...selected, grade.id]);
    }

    if (nextIds.length === orgFieldIds.length && orgFieldIds.every((id) => nextIds.includes(id))) {
      // all selected — grade stays checked
    }
  };

  return (
    <div className="rounded-2xl border border-[var(--border)] bg-white p-4">
      <h3 className="mb-3 text-sm font-bold">مقاطع و پایه‌های تحصیلی</h3>
      <p className="mb-3 text-xs leading-relaxed text-[var(--muted)]">
        {description}
      </p>
      <div className="max-h-[32rem] space-y-2 overflow-y-auto text-sm">
        {stages.map((stage) => {
          const grades = stage.grade_levels ?? [];
          const gradeIds = grades.map((g) => g.id);
          const allGradesSelected =
            gradeIds.length > 0 && gradeIds.every((id) => selected.includes(id));
          const allFieldsComplete = grades.every((grade) => {
            if (!gradeNeedsFieldChoice(grade)) return true;
            const ids = fieldSelections[grade.id] ?? [];
            return grade.study_fields.every((f) => ids.includes(f.id));
          });
          const stageChecked = allGradesSelected && allFieldsComplete;
          const stageIndeterminate =
            !stageChecked &&
            (gradeIds.some((id) => selected.includes(id)) ||
              grades.some((grade) => {
                if (!gradeNeedsFieldChoice(grade)) return false;
                const ids = fieldSelections[grade.id] ?? [];
                return ids.length > 0 && ids.length < grade.study_fields.length;
              }));

          return (
            <div key={stage.id} className="rounded-xl border border-[var(--border)] p-2">
              <label className="flex cursor-pointer items-center gap-2 font-semibold">
                <input
                  type="checkbox"
                  checked={stageChecked}
                  disabled={readOnlyGrades}
                  ref={(el) => {
                    if (el) el.indeterminate = stageIndeterminate;
                  }}
                  onChange={() => toggleStage(stage)}
                />
                {stage.name}
              </label>
              <div className="mr-6 mt-1 space-y-2">
                {grades.map((grade) => {
                  const isSelected = selected.includes(grade.id);
                  const orgFieldIds = grade.study_fields.map((f) => f.id);
                  const selectedFields = fieldSelections[grade.id] ?? [];
                  const needsChoice = gradeNeedsFieldChoice(grade);
                  const allFieldsSelected =
                    orgFieldIds.length > 0 &&
                    orgFieldIds.every((id) => selectedFields.includes(id));
                  const gradeChecked = isSelected && (!needsChoice || allFieldsSelected);
                  const gradeIndeterminate =
                    isSelected && needsChoice && selectedFields.length > 0 && !allFieldsSelected;
                  const expanded = expandedGrades.includes(grade.id);

                  return (
                    <div key={grade.id} className="space-y-1">
                      {needsChoice ? (
                        <div className="flex items-center gap-2 text-[var(--muted)]">
                          <input
                            type="checkbox"
                            checked={gradeChecked}
                            disabled={readOnlyGrades}
                            ref={(el) => {
                              if (el) el.indeterminate = gradeIndeterminate;
                            }}
                            onChange={() => toggleGrade(grade)}
                          />
                          <button
                            type="button"
                            className="flex min-w-0 flex-1 items-center justify-between gap-2 text-right"
                            onClick={() => toggleExpanded(grade.id)}
                          >
                            <span>{grade.name}</span>
                            <svg
                              viewBox="0 0 24 24"
                              className={`h-3.5 w-3.5 shrink-0 text-slate-400 transition-transform ${
                                expanded ? "rotate-180" : ""
                              }`}
                              fill="none"
                              stroke="currentColor"
                              strokeWidth="1.5"
                              aria-hidden
                            >
                              <path
                                d="M6 9l6 6 6-6"
                                strokeLinecap="round"
                                strokeLinejoin="round"
                              />
                            </svg>
                          </button>
                        </div>
                      ) : (
                        <label className="flex cursor-pointer items-center gap-2 text-[var(--muted)]">
                          <input
                            type="checkbox"
                            checked={gradeChecked}
                            disabled={readOnlyGrades}
                            onChange={() => toggleGrade(grade)}
                          />
                          {grade.name}
                        </label>
                      )}
                      {needsChoice && expanded ? (
                        <div className="mr-6 flex flex-wrap gap-x-3 gap-y-1">
                          {grade.study_fields.map((field) => (
                            <label
                              key={field.id}
                              className="flex cursor-pointer items-center gap-1.5 text-xs text-[var(--muted)]"
                            >
                              <input
                                type="checkbox"
                                checked={selectedFields.includes(field.id)}
                                onChange={() => toggleField(grade, field.id)}
                              />
                              {field.name}
                            </label>
                          ))}
                        </div>
                      ) : null}
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
