import { useState } from "react";
import Shell from "../components/Shell";
import {
    Alert,
    Badge,
    Button,
    Confirm,
    Dialog,
    Errors,
    Field,
    Heading,
    Panel,
    SaveForm,
    Empty,
} from "../components/ui";
import {
    person,
    type Course as SubjectClass,
    type Grade,
    type Student,
} from "../types";

export default function Course({
    course: c,
    can_teach,
    roster,
    grades,
}: {
    course: SubjectClass;
    can_teach: boolean;
    roster: Student[];
    grades: Grade[];
}) {
    const [editing, setEditing] = useState<Student | null>(null);
    const [finalize, setFinalize] = useState(false);
    const grade = grades.find((g) => g.student_id === editing?.id);
    const correcting = !!grade?.finalized_at;
    const missing = roster.some(
        (s) => !grades.some((g) => g.student_id === s.id),
    );
    const locked = !!c.finalized_at;
    const numericValues = [
        ...new Set(c.policy_snapshot.conversions.map((r) => Number(r.grade))),
    ];
    return (
        <Shell title={c.subject.code + " · " + c.section}>
            <Heading
                title={c.subject.code + " · " + c.subject.name}
                description={
                    c.period.name +
                    " · Class " +
                    c.section +
                    " · " +
                    c.branch.name
                }
                action={
                    can_teach && !locked ? (
                        <Button
                            onClick={() => setFinalize(true)}
                            disabled={missing || !roster.length}
                        >
                            Finalize final grades
                        </Button>
                    ) : undefined
                }
            />
            <Panel title="Class details">
                <div className="form-grid">
                    <div>
                        <small>Assigned Teacher</small>
                        <strong>{c.teacher.name}</strong>
                    </div>
                    <div>
                        <small>Current schedule</small>
                        <strong>
                            {c.schedule ||
                                "Awaiting School Administrator review"}
                        </strong>
                    </div>
                    <div>
                        <small>Usual Sections</small>
                        <strong>
                            {c.sections?.map((s) => s.name).join(", ") ||
                                "Individual class selections"}
                        </strong>
                    </div>
                    <div>
                        <small>Credit units</small>
                        <strong>{c.subject.units}</strong>
                    </div>
                </div>
            </Panel>
            {can_teach && !locked && (
                <Alert title="Enter the final subject result directly">
                    Use the school’s assigned grade scale. Save draft grades,
                    review them, then finalize.{" "}
                    {missing
                        ? "Some Students still need a final-grade entry."
                        : "All enrolled Students have an entered grade."}
                </Alert>
            )}
            {locked && (
                <Alert title="Final grades are official" tone="success">
                    The assigned Teacher can record a correction with a reason.
                    Previous results are retained in history.
                </Alert>
            )}
            <Panel title="Class roster and final grades">
                {!roster.length && (
                    <Empty title="No enrolled Students">
                        Students appear after the Registrar finalizes enrollment
                        for this Subject Class.
                    </Empty>
                )}
                {roster.map((student) => {
                    const result = grades.find(
                        (g) => g.student_id === student.id,
                    );
                    return (
                        <article className="student-grade-row" key={student.id}>
                            <div>
                                <strong>{person(student)}</strong>
                                <small>{student.student_number}</small>
                            </div>
                            <div>
                                <small>Final subject grade</small>
                                <strong>
                                    {result?.official_grade ?? "Not entered"}
                                </strong>
                            </div>
                            <div>
                                <Badge
                                    tone={
                                        result?.finalized_at
                                            ? result.passed
                                                ? "success"
                                                : "danger"
                                            : "warning"
                                    }
                                >
                                    {result?.finalized_at
                                        ? result.passed
                                            ? "Passed · Official"
                                            : "Failed · Official"
                                        : result
                                          ? "Draft"
                                          : "Awaiting entry"}
                                </Badge>
                            </div>
                            {can_teach && (
                                <Button
                                    type="button"
                                    variant="secondary"
                                    onClick={() => setEditing(student)}
                                >
                                    {result?.finalized_at
                                        ? "Correct grade"
                                        : result
                                          ? "Edit draft grade"
                                          : "Enter final grade"}
                                </Button>
                            )}
                            {!!result?.corrections?.length && (
                                <details className="accordion grade-history">
                                    <summary>Grade correction history</summary>
                                    <div>
                                        {result.corrections.map((change) => (
                                            <p key={change.id}>
                                                <strong>
                                                    {change.old_grade} →{" "}
                                                    {change.new_grade}
                                                </strong>
                                                <br />
                                                {change.reason}
                                                <br />
                                                <small>
                                                    {new Date(
                                                        change.created_at,
                                                    ).toLocaleDateString(
                                                        "en-PH",
                                                    )}
                                                </small>
                                            </p>
                                        ))}
                                    </div>
                                </details>
                            )}
                        </article>
                    );
                })}
            </Panel>
            {editing && (
                <Dialog
                    title={
                        (correcting
                            ? "Correct final grade · "
                            : "Enter final grade · ") + person(editing)
                    }
                    onClose={() => setEditing(null)}
                >
                    <Errors />
                    <SaveForm
                        url={
                            correcting
                                ? "/classes/" +
                                  c.id +
                                  "/grades/" +
                                  grade!.id +
                                  "/correct"
                                : "/classes/" +
                                  c.id +
                                  "/students/" +
                                  editing.id +
                                  "/grade"
                        }
                        method={correcting ? "post" : "put"}
                        label={
                            correcting
                                ? "Record grade correction"
                                : "Save draft final grade"
                        }
                        onSuccess={() => setEditing(null)}
                    >
                        <p>
                            {editing.student_number} · {c.subject.code} ·{" "}
                            {c.policy_snapshot.name}
                        </p>
                        <Field label="Final subject grade">
                            {c.policy_snapshot.scale === "numeric" ? (
                                <select
                                    name="grade"
                                    required
                                    defaultValue={
                                        grade
                                            ? String(
                                                  Number(grade.official_grade),
                                              )
                                            : ""
                                    }
                                >
                                    <option value="">
                                        Choose the official grade
                                    </option>
                                    {numericValues.map((value) => (
                                        <option key={value} value={value}>
                                            {value.toFixed(2)}
                                        </option>
                                    ))}
                                </select>
                            ) : (
                                <input
                                    name="grade"
                                    type="number"
                                    min={0}
                                    max={100}
                                    step="0.01"
                                    required
                                    defaultValue={grade?.official_grade}
                                />
                            )}
                        </Field>
                        <Field
                            label={
                                correcting
                                    ? "Correction reason"
                                    : "Notes (optional)"
                            }
                        >
                            <textarea
                                name="reason"
                                required={correcting}
                                minLength={5}
                                maxLength={2000}
                            />
                        </Field>
                        <p className="small">
                            {correcting
                                ? "The previous result and this correction’s reason are retained."
                                : "The entered result remains a draft until the assigned Teacher finalizes it."}
                        </p>
                    </SaveForm>
                </Dialog>
            )}
            {finalize && (
                <Confirm
                    title="Finalize the reviewed final grades?"
                    url={"/classes/" + c.id + "/finalize"}
                    onClose={() => setFinalize(false)}
                >
                    These results become official and can satisfy prerequisite
                    checks. The Registrar can no longer drop or switch these
                    Students’ graded subjects. Later grade corrections require a
                    reason.
                </Confirm>
            )}
        </Shell>
    );
}
