"use client";

import { useCallback, useEffect, useState, type Dispatch, type ReactNode, type SetStateAction } from "react";
import Link from "next/link";
import { BuildingPicker } from "@/components/buildings/BuildingPicker";
import { GradeLevelTree } from "@/components/schools/GradeLevelTree";
import { MapPicker } from "@/components/schools/MapPicker";
import { Field, Input } from "@/components/ui/Field";
import { FormErrorSummary } from "@/components/forms/FormErrorSummary";
import { ApiError, apiGet } from "@/lib/api";
import type { BuildingSummary } from "@/lib/buildings";
import type { StudyFieldMatrixStage } from "@/lib/types";

export interface SchoolFormValues {
  name: string;
  code: string;
  school_type: string;
  manager_user_id: number | null;
  manager_label: string;
  primary_building_id: number | null;
  primary_building: BuildingSummary | null;
  settings: {
    phone: string;
  };
  grade_level_ids: number[];
  grade_study_fields: Record<number, number[]>;
}

export const emptySchoolForm = (): SchoolFormValues => ({
  name: "",
  code: "",
  school_type: "",
  manager_user_id: null,
  manager_label: "",
  primary_building_id: null,
  primary_building: null,
  settings: {
    phone: "",
  },
  grade_level_ids: [],
  grade_study_fields: {},
});

export type SchoolFormFieldErrors = Partial<{
  name: string;
  code: string;
  manager_user_id: string;
  primary_building_id: string;
  phone: string;
  grade_study_fields: string;
}>;

export function validateSchoolForm(value: SchoolFormValues): SchoolFormFieldErrors {
  const errors: SchoolFormFieldErrors = {};
  if (!value.name.trim()) errors.name = "نام مدرسه الزامی است.";
  if (!value.code.trim()) errors.code = "کد مدرسه الزامی است.";
  if (!value.primary_building_id) errors.primary_building_id = "انتخاب ساختمان مرکزی شعبه الزامی است.";
  return errors;
}

export function schoolFormErrorMessages(
  errors: SchoolFormFieldErrors,
  general?: string | null,
): string[] {
  const messages = Object.values(errors).filter((message): message is string => Boolean(message));
  if (general && !messages.includes(general)) messages.push(general);
  return messages;
}

export function schoolFormErrorsFromApi(err: unknown): {
  fields: SchoolFormFieldErrors;
  general: string | null;
} {
  if (!(err instanceof ApiError)) {
    return { fields: {}, general: "خطا در ثبت مدرسه" };
  }

  const payload = err.payload as { errors?: Record<string, string[]> } | undefined;
  const raw = payload?.errors ?? {};
  const fields: SchoolFormFieldErrors = {};
  const mapping: Array<[string, keyof SchoolFormFieldErrors]> = [
    ["name", "name"],
    ["code", "code"],
    ["manager_user_id", "manager_user_id"],
    ["primary_building_id", "primary_building_id"],
    ["settings.phone", "phone"],
    ["grade_study_fields", "grade_study_fields"],
  ];
  const used = new Set<string>();
  for (const [apiKey, fieldKey] of mapping) {
    const message = raw[apiKey]?.[0];
    if (message) {
      fields[fieldKey] = message;
      used.add(apiKey);
    }
  }

  const leftover = Object.entries(raw)
    .filter(([key]) => !used.has(key))
    .flatMap(([, messages]) => messages);

  return {
    fields,
    general: leftover[0] ?? (Object.keys(fields).length === 0 ? err.message : null),
  };
}

interface ManagerOption {
  id: number;
  name: string;
  national_code?: string | null;
}

export function SchoolForm({
  value,
  onChange,
  errors = {},
  onErrorsChange,
  actions,
  generalError,
}: {
  value: SchoolFormValues;
  onChange: Dispatch<SetStateAction<SchoolFormValues>>;
  errors?: SchoolFormFieldErrors;
  onErrorsChange?: Dispatch<SetStateAction<SchoolFormFieldErrors>>;
  actions?: ReactNode;
  generalError?: string | null;
}) {
  const [stages, setStages] = useState<StudyFieldMatrixStage[]>([]);
  const [managerQuery, setManagerQuery] = useState(value.manager_label);
  const [managerOptions, setManagerOptions] = useState<ManagerOption[]>([]);

  useEffect(() => {
    apiGet<StudyFieldMatrixStage[]>("/study-fields/matrix").then(setStages).catch(() => setStages([]));
  }, []);

  useEffect(() => {
    setManagerQuery(value.manager_label);
  }, [value.manager_label]);

  const searchManagers = useCallback(async (q: string) => {
    setManagerQuery(q);
    onChange((prev) => ({ ...prev, manager_label: q, manager_user_id: null }));
    if (q.length < 2) {
      setManagerOptions([]);
      return;
    }
    try {
      const results = await apiGet<ManagerOption[]>(
        `/users/search?q=${encodeURIComponent(q)}`,
      );
      setManagerOptions(results);
    } catch {
      setManagerOptions([]);
    }
  }, [onChange]);

  const clearError = (key: keyof SchoolFormFieldErrors) => {
    onErrorsChange?.((prev) => {
      if (!prev[key]) return prev;
      const next = { ...prev };
      delete next[key];
      return next;
    });
  };

  const patch = (partial: Partial<SchoolFormValues>) =>
    onChange((prev) => ({ ...prev, ...partial }));

  const patchSettings = (partial: Partial<SchoolFormValues["settings"]>) =>
    onChange((prev) => ({ ...prev, settings: { ...prev.settings, ...partial } }));

  const building = value.primary_building;

  return (
    <div className="space-y-4">
      <div className="grid gap-6 lg:grid-cols-[1fr,20rem]">
      <div className="space-y-4 rounded-2xl border border-[var(--border)] bg-white p-4">
        <h3 className="text-base font-bold">اطلاعات مدرسه</h3>
        <div className="grid gap-3 sm:grid-cols-2">
          <Field label="نام مدرسه *" error={errors.name}>
            <Input
              value={value.name}
              invalid={Boolean(errors.name)}
              onChange={(e) => {
                patch({ name: e.target.value });
                clearError("name");
              }}
            />
          </Field>
          <Field label="کد منحصر به فرد *" error={errors.code}>
            <Input
              value={value.code}
              invalid={Boolean(errors.code)}
              onChange={(e) => {
                patch({ code: e.target.value });
                clearError("code");
              }}
            />
          </Field>
        </div>

        <Field label="مدیر مدرسه" error={errors.manager_user_id}>
          <Input
            value={managerQuery}
            invalid={Boolean(errors.manager_user_id)}
            placeholder="قسمتی از نام را وارد کنید"
            onChange={(e) => {
              searchManagers(e.target.value);
              clearError("manager_user_id");
            }}
          />
          {managerOptions.length > 0 ? (
            <ul className="mt-1 max-h-32 overflow-y-auto rounded-xl border border-[var(--border)] bg-white text-sm shadow-sm">
              {managerOptions.map((m) => (
                <li key={m.id}>
                  <button
                    type="button"
                    className="block w-full px-3 py-2 text-right hover:bg-slate-50"
                    onClick={() => {
                      setManagerQuery(m.name);
                      setManagerOptions([]);
                      onChange((prev) => ({
                        ...prev,
                        manager_user_id: m.id,
                        manager_label: m.name,
                      }));
                    }}
                  >
                    {m.name}
                    {m.national_code ? (
                      <span className="mr-2 font-mono text-xs text-[var(--muted)]">{m.national_code}</span>
                    ) : null}
                  </button>
                </li>
              ))}
            </ul>
          ) : null}
        </Field>

        <Field label="نوع مدرسه">
          <div className="flex flex-wrap gap-4 pt-1">
            {[
              { v: "", l: "مختلط" },
              { v: "boys", l: "پسرانه" },
              { v: "girls", l: "دخترانه" },
            ].map(({ v, l }) => (
              <label key={l} className="flex cursor-pointer items-center gap-2">
                <input
                  type="radio"
                  name="school_type"
                  checked={value.school_type === v}
                  onChange={() => patch({ school_type: v })}
                />
                {l}
              </label>
            ))}
          </div>
        </Field>

        <div className="grid gap-3 sm:grid-cols-2">
          <Field label="تلفن مدرسه" error={errors.phone}>
            <Input
              value={value.settings.phone}
              invalid={Boolean(errors.phone)}
              onChange={(e) => {
                patchSettings({ phone: e.target.value });
                clearError("phone");
              }}
            />
          </Field>
        </div>

        <BuildingPicker
          value={value.primary_building_id}
          selected={value.primary_building}
          error={errors.primary_building_id}
          onClearError={() => clearError("primary_building_id")}
          onSelect={(building) => {
            onChange((prev) => ({
              ...prev,
              primary_building_id: building?.id ?? null,
              primary_building: building,
            }));
          }}
        />
        <p className="text-xs text-[var(--muted)]">
          ساختمان در فهرست نیست؟ ابتدا از{" "}
          <Link href="/buildings/new" className="text-teal-700 hover:underline">
            مدیریت ساختمان‌ها
          </Link>{" "}
          ثبت کنید.
        </p>

        {building ? (
          <div className="space-y-3 rounded-xl border border-[var(--border)] bg-slate-50 p-3">
            <h4 className="text-sm font-bold">آدرس و موقعیت ساختمان مرکزی</h4>
            <dl className="grid gap-2 text-sm sm:grid-cols-2">
              <div>
                <dt className="text-xs text-[var(--muted)]">استان</dt>
                <dd>{building.province || "—"}</dd>
              </div>
              <div>
                <dt className="text-xs text-[var(--muted)]">شهر</dt>
                <dd>{building.city || "—"}</dd>
              </div>
              <div className="sm:col-span-2">
                <dt className="text-xs text-[var(--muted)]">آدرس</dt>
                <dd>{building.address || "—"}</dd>
              </div>
              <div>
                <dt className="text-xs text-[var(--muted)]">کد پستی</dt>
                <dd>{building.postal_code || "—"}</dd>
              </div>
            </dl>
            <MapPicker
              readOnly
              lat={building.latitude ?? building.map?.lat ?? null}
              lng={building.longitude ?? building.map?.lng ?? null}
            />
          </div>
        ) : null}

        {actions ? <div className="flex gap-3 pt-2">{actions}</div> : null}
      </div>

      <div className="space-y-2">
        <GradeLevelTree
          stages={stages}
          selected={value.grade_level_ids}
          onChange={(grade_level_ids) => {
            onChange((prev) => ({ ...prev, grade_level_ids }));
            clearError("grade_study_fields");
          }}
          gradeStudyFields={value.grade_study_fields}
          onGradeStudyFieldsChange={(grade_study_fields) => {
            onChange((prev) => ({ ...prev, grade_study_fields }));
            clearError("grade_study_fields");
          }}
        />
        {errors.grade_study_fields ? (
          <p className="text-xs text-red-600">{errors.grade_study_fields}</p>
        ) : null}
      </div>
    </div>

      <FormErrorSummary errors={errors} general={generalError} />
    </div>
  );
}
