import { Form, Head, Link, router } from '@inertiajs/react';
import { format } from 'date-fns';
import { ArrowLeft, Check, Inbox, Send, X } from 'lucide-react';
import { useState } from 'react';
import { FormDialog } from '@/components/form-dialog';
import InputError from '@/components/input-error';
import { PageHeader } from '@/components/page-header';
import { SignaturePad } from '@/components/signature-pad';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import {
    Table,
    TableBody,
    TableCell,
    TableFooter,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Textarea } from '@/components/ui/textarea';
import {
    advisor_signature,
    approve,
    kaprodi_signature,
    reject,
    save,
} from '@/routes/admin/manage/course-registrations';
import type {
    CourseRegistrationSubmission,
    CourseRegistrationSubmissionEntry,
    CourseRegistrationSubmissionLog,
} from '@/types/course-registration';
import {
    RegistrationStatusLabels,
    semesterKey,
} from '@/types/course-registration';

const RegistrationStatusVariants: Record<
    CourseRegistrationSubmission['status'],
    'default' | 'secondary' | 'destructive' | 'outline'
> = {
    submitted: 'outline',
    approved: 'default',
    rejected: 'destructive',
};

function isSemesterOpenForStudent(
    semester: number | null,
    openSemesters: number[],
    studentCurrentSemester: number,
): boolean {
    return (
        semester !== null &&
        semester === studentCurrentSemester &&
        openSemesters.includes(semester)
    );
}

function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
    return (
        <div className="grid grid-cols-[auto_1fr] gap-x-2 text-sm">
            <span className="text-muted-foreground">{label}</span>
            <span className="font-medium">: {value}</span>
        </div>
    );
}

function SignatureBox({
    signatureUrl,
    alt,
    error,
    editable,
}: {
    signatureUrl: string | null;
    alt: string;
    error?: string;
    editable: boolean;
}) {
    if (!editable) {
        if (!signatureUrl) {
            return <div className="h-28 w-48" />;
        }

        return (
            <div className="h-28 w-48 overflow-hidden rounded border bg-white">
                <img
                    src={signatureUrl}
                    alt={alt}
                    className="h-full w-full object-contain"
                />
            </div>
        );
    }

    return <SignaturePad name="signature" error={error} compact />;
}

function ReviewerSignatureField({
    signatureUrl,
    alt,
    canSign,
    submitUrl,
}: {
    signatureUrl: string | null;
    alt: string;
    canSign: boolean;
    submitUrl: string;
}) {
    const [file, setFile] = useState<File | null>(null);
    const [processing, setProcessing] = useState(false);

    if (signatureUrl) {
        return (
            <div className="h-28 w-48 overflow-hidden rounded border bg-white">
                <img
                    src={signatureUrl}
                    alt={alt}
                    className="h-full w-full object-contain"
                />
            </div>
        );
    }

    if (!canSign) {
        return <div className="h-28 w-48" />;
    }

    function handleSave() {
        if (!file) {
            return;
        }

        setProcessing(true);
        router.patch(
            submitUrl,
            { signature: file },
            {
                preserveScroll: true,
                onFinish: () => setProcessing(false),
            },
        );
    }

    return (
        <div className="grid gap-1">
            <SignaturePad name="_signature" compact onCapture={setFile} />
            <Button
                type="button"
                size="sm"
                disabled={!file || processing}
                onClick={handleSave}
            >
                {processing ? 'Menyimpan...' : 'Simpan TTD'}
            </Button>
        </div>
    );
}

function LogBubble({
    log,
    isResubmission,
}: {
    log: CourseRegistrationSubmissionLog;
    isResubmission: boolean;
}) {
    const actorName = log.actor?.profile?.full_name ?? 'Sistem';

    const message =
        log.status === 'approved'
            ? `${actorName} menyetujui KRS ini.`
            : log.status === 'rejected'
              ? `${actorName} menolak KRS ini dengan alasan: "${log.reason}"`
              : isResubmission
                ? `${actorName} mengajukan ulang KRS.`
                : `${actorName} mengajukan KRS.`;

    const colorClasses =
        log.status === 'approved'
            ? 'border-primary/30 bg-primary/10'
            : log.status === 'rejected'
              ? 'border-destructive/30 bg-destructive/10'
              : 'border-border bg-muted';

    return (
        <div className={`rounded-lg border px-3 py-2 ${colorClasses}`}>
            <p className="text-sm">{message}</p>
            <p className="mt-1 text-xs text-muted-foreground">
                {format(new Date(log.created_at), 'd MMM yyyy, HH:mm')}
            </p>
        </div>
    );
}

function RejectDialog({
    open,
    onOpenChange,
    submissionId,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    submissionId: number;
}) {
    return (
        <FormDialog
            open={open}
            onOpenChange={onOpenChange}
            title="Tolak Registrasi KRS"
            action={reject(submissionId)}
            resetOnSuccess
            onSuccess={() => onOpenChange(false)}
        >
            {({ errors }) => (
                <div className="grid gap-2">
                    <Label htmlFor="reason">
                        Alasan Penolakan{' '}
                        <span className="text-destructive">*</span>
                    </Label>
                    <Textarea
                        id="reason"
                        name="reason"
                        placeholder="Jelaskan alasan penolakan"
                    />
                    <InputError message={errors.reason} />
                </div>
            )}
        </FormDialog>
    );
}

function SemesterCard({
    semester,
    submission,
    studentId,
    isSemesterOpen,
    backHref,
    canReview,
    canSignAsKaprodi,
    canSignAsAdvisor,
}: {
    semester: number | null;
    submission: CourseRegistrationSubmission;
    studentId: number;
    isSemesterOpen: boolean;
    backHref: string | null;
    canReview: boolean;
    canSignAsKaprodi: boolean;
    canSignAsAdvisor: boolean;
}) {
    const [rejecting, setRejecting] = useState(false);

    const student = submission.student;
    const department = student?.department ?? null;
    const kaprodi = department?.current_leader?.lecturer ?? null;
    const advisor = student?.academic_advisor ?? null;

    const isViewOnly = backHref !== null;
    const notYetSubmitted =
        submission.status === 'submitted' && !submission.has_registrations;
    const isLocked =
        submission.status === 'approved' ||
        (submission.status === 'submitted' && submission.has_registrations);
    const canDecide =
        canReview && submission.status === 'submitted' && !notYetSubmitted;
    const canReviewersSign =
        submission.status === 'submitted' && !notYetSubmitted;
    const missingKaprodiSignature = !submission.kaprodi_signature_url;
    const missingOwnSignature =
        (canSignAsKaprodi && !submission.kaprodi_signature_url) ||
        (canSignAsAdvisor && !submission.advisor_signature_url);
    const cannotApprove = missingKaprodiSignature || missingOwnSignature;

    const totalCredits = submission.course_registrations.reduce(
        (sum, registration) =>
            submission.has_registrations
                ? registration.is_registered
                    ? sum + registration.course.credits
                    : sum
                : isSemesterOpen && registration.course_class
                  ? sum + registration.course.credits
                  : sum,
        0,
    );

    function handleApprove() {
        router.patch(approve.url(submission.id), {}, { preserveScroll: true });
    }

    return (
        <Form
            action={save([studentId, semesterKey(semester)])}
            options={{ preserveScroll: true }}
            className="flex flex-col gap-6"
        >
            {({ processing, errors }) => (
                <>
                    <Card>
                        <CardContent className="p-6 sm:p-8">
                            <div className="flex flex-col items-center gap-1 text-center">
                                <h2 className="text-lg font-bold tracking-wide uppercase">
                                    Kartu Rencana Studi
                                </h2>
                                <Badge
                                    variant={
                                        notYetSubmitted
                                            ? 'secondary'
                                            : RegistrationStatusVariants[
                                                  submission.status
                                              ]
                                    }
                                >
                                    {notYetSubmitted
                                        ? 'Belum Diajukan'
                                        : RegistrationStatusLabels[
                                              submission.status
                                          ]}
                                </Badge>
                            </div>

                            <div className="mt-6 flex flex-col justify-between gap-4 sm:flex-row">
                                <div className="grid gap-1">
                                    <InfoRow
                                        label="Nama"
                                        value={
                                            student?.user?.profile?.full_name ??
                                            'N/A'
                                        }
                                    />
                                    <InfoRow
                                        label="NIM"
                                        value={student?.student_number ?? '-'}
                                    />
                                </div>
                                <div className="grid gap-1 sm:text-right">
                                    <InfoRow
                                        label="Program Studi"
                                        value={department?.name ?? '-'}
                                    />
                                    <InfoRow
                                        label="Dosen Pembimbing Akademik"
                                        value={
                                            student?.academic_advisor?.user
                                                ?.profile?.full_name ?? '-'
                                        }
                                    />
                                </div>
                            </div>

                            <div className="mt-6 overflow-x-auto rounded-md border">
                                <Table>
                                    <TableHeader>
                                        <TableRow>
                                            <TableHead className="w-[40px]">
                                                No
                                            </TableHead>
                                            <TableHead>Mata Kuliah</TableHead>
                                            <TableHead>Kode</TableHead>
                                            <TableHead className="text-center">
                                                SKS
                                            </TableHead>
                                            <TableHead className="w-[40px] text-center">
                                                Ambil
                                            </TableHead>
                                        </TableRow>
                                    </TableHeader>
                                    <TableBody>
                                        {submission.course_registrations
                                            .length === 0 ? (
                                            <TableRow>
                                                <TableCell
                                                    colSpan={5}
                                                    className="text-center text-muted-foreground"
                                                >
                                                    Belum ada mata kuliah yang
                                                    dipilih.
                                                </TableCell>
                                            </TableRow>
                                        ) : (
                                            submission.course_registrations.map(
                                                (
                                                    registration: CourseRegistrationSubmissionEntry,
                                                    index,
                                                ) => {
                                                    const course =
                                                        registration.course;
                                                    const checked =
                                                        submission.has_registrations
                                                            ? registration.is_registered
                                                            : isSemesterOpen;

                                                    return (
                                                        <TableRow
                                                            key={
                                                                registration.id
                                                            }
                                                        >
                                                            <TableCell>
                                                                {index + 1}
                                                            </TableCell>
                                                            <TableCell>
                                                                {course.name}
                                                            </TableCell>
                                                            <TableCell>
                                                                {course.code}
                                                            </TableCell>
                                                            <TableCell className="text-center">
                                                                {
                                                                    course.credits
                                                                }
                                                            </TableCell>
                                                            <TableCell className="text-center">
                                                                {registration.course_class ? (
                                                                    <Checkbox
                                                                        name="course_class_ids[]"
                                                                        value={
                                                                            registration
                                                                                .course_class
                                                                                .id
                                                                        }
                                                                        defaultChecked={
                                                                            checked
                                                                        }
                                                                        disabled={
                                                                            !isSemesterOpen ||
                                                                            isViewOnly ||
                                                                            isLocked
                                                                        }
                                                                    />
                                                                ) : (
                                                                    <span
                                                                        className="text-xs text-muted-foreground"
                                                                        title="Kelas belum dibuka untuk periode ini"
                                                                    >
                                                                        —
                                                                    </span>
                                                                )}
                                                            </TableCell>
                                                        </TableRow>
                                                    );
                                                },
                                            )
                                        )}
                                    </TableBody>
                                    {submission.course_registrations.length >
                                        0 && (
                                        <TableFooter>
                                            <TableRow>
                                                <TableCell
                                                    colSpan={3}
                                                    className="text-right font-medium"
                                                >
                                                    Total SKS
                                                </TableCell>
                                                <TableCell className="text-center font-medium">
                                                    {totalCredits}
                                                </TableCell>
                                                <TableCell />
                                            </TableRow>
                                        </TableFooter>
                                    )}
                                </Table>
                            </div>

                            <div className="mt-10 grid gap-6">
                                <div className="flex flex-col gap-8 sm:flex-row sm:justify-around">
                                    <div className="grid gap-1 text-sm">
                                        <p>Menyetujui,</p>
                                        <p>Ketua Program Studi,</p>
                                        <ReviewerSignatureField
                                            signatureUrl={
                                                submission.kaprodi_signature_url
                                            }
                                            alt="Tanda tangan Ketua Program Studi"
                                            canSign={
                                                canSignAsKaprodi &&
                                                canReviewersSign
                                            }
                                            submitUrl={kaprodi_signature.url([
                                                studentId,
                                                semesterKey(semester),
                                            ])}
                                        />
                                        <p className="font-semibold">
                                            {kaprodi?.user?.profile
                                                ?.full_name ?? '-'}
                                        </p>
                                        <p className="text-xs text-muted-foreground">
                                            NIDN.{' '}
                                            {kaprodi?.lecturer_number ?? '-'}
                                        </p>
                                    </div>

                                    <div className="grid gap-1 text-sm">
                                        <p>Disetujui oleh,</p>
                                        <p>Pembimbing Akademik,</p>
                                        <ReviewerSignatureField
                                            signatureUrl={
                                                submission.advisor_signature_url
                                            }
                                            alt="Tanda tangan Pembimbing Akademik"
                                            canSign={
                                                canSignAsAdvisor &&
                                                canReviewersSign
                                            }
                                            submitUrl={advisor_signature.url([
                                                studentId,
                                                semesterKey(semester),
                                            ])}
                                        />
                                        <p className="font-semibold">
                                            {advisor?.user?.profile
                                                ?.full_name ?? '-'}
                                        </p>
                                        <p className="text-xs text-muted-foreground">
                                            NIDN.{' '}
                                            {advisor?.lecturer_number ?? '-'}
                                        </p>
                                    </div>

                                    <div className="grid gap-1 text-sm">
                                        <p>Mahasiswa,</p>
                                        <SignatureBox
                                            signatureUrl={
                                                submission.signature_url
                                            }
                                            alt="Tanda tangan mahasiswa"
                                            error={errors.signature}
                                            editable={
                                                isSemesterOpen &&
                                                !isViewOnly &&
                                                !isLocked
                                            }
                                        />
                                        <p className="font-semibold">
                                            {student?.user?.profile
                                                ?.full_name ?? 'N/A'}
                                        </p>
                                        <p className="text-xs text-muted-foreground">
                                            NIM.{' '}
                                            {student?.student_number ?? '-'}
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </CardContent>
                    </Card>

                    {!backHref && !isLocked && isSemesterOpen && (
                        <div className="flex justify-end">
                            <Button type="submit" disabled={processing}>
                                <Send className="h-4 w-4" />
                                {processing ? 'Mengajukan...' : 'Ajukan'}
                            </Button>
                        </div>
                    )}

                    {canDecide && (
                        <div className="flex flex-col items-end gap-2">
                            <div className="flex gap-2">
                                <Button
                                    type="button"
                                    variant="destructive"
                                    onClick={() => setRejecting(true)}
                                >
                                    <X className="h-4 w-4" />
                                    Tolak
                                </Button>
                                <Button
                                    type="button"
                                    disabled={cannotApprove}
                                    onClick={handleApprove}
                                >
                                    <Check className="h-4 w-4" />
                                    Setujui
                                </Button>
                            </div>
                            {cannotApprove && (
                                <p className="text-xs text-muted-foreground">
                                    {missingKaprodiSignature
                                        ? 'Menunggu tanda tangan Ketua Program Studi sebelum dapat disetujui.'
                                        : 'Silakan tanda tangani KRS ini terlebih dahulu sebelum menyetujui.'}
                                </p>
                            )}
                        </div>
                    )}

                    <Card>
                        <CardHeader>
                            <CardTitle className="text-base">Riwayat</CardTitle>
                        </CardHeader>
                        <CardContent className="grid gap-2">
                            {submission.logs.map((log, index) => (
                                <LogBubble
                                    key={log.id}
                                    log={log}
                                    isResubmission={
                                        log.status === 'submitted' &&
                                        submission.logs
                                            .slice(0, index)
                                            .some(
                                                (l) => l.status === 'submitted',
                                            )
                                    }
                                />
                            ))}
                        </CardContent>
                    </Card>

                    <RejectDialog
                        open={rejecting}
                        onOpenChange={setRejecting}
                        submissionId={submission.id}
                    />
                </>
            )}
        </Form>
    );
}

type Props = {
    submissions: Record<string, CourseRegistrationSubmission>;
    semesters: (number | null)[];
    openSemesters: number[];
    studentCurrentSemester: number;
    hasActiveTerm: boolean;
    backHref: string | null;
    canReview: boolean;
    canSignAsKaprodi: boolean;
    canSignAsAdvisor: boolean;
};

export default function CourseRegistrationDetail({
    submissions,
    semesters,
    openSemesters,
    studentCurrentSemester,
    hasActiveTerm,
    backHref,
    canReview,
    canSignAsKaprodi,
    canSignAsAdvisor,
}: Props) {
    const [activeSemester, setActiveSemester] = useState(() =>
        semesterKey(semesters[0] ?? null),
    );
    const currentKey = semesters.some(
        (semester) => semesterKey(semester) === activeSemester,
    )
        ? activeSemester
        : semesterKey(semesters[0] ?? null);

    const currentSemester =
        semesters.find((semester) => semesterKey(semester) === currentKey) ??
        null;
    const currentSubmission = submissions[currentKey];
    const studentId = Object.values(submissions)[0]?.student?.id ?? 0;

    return (
        <>
            <Head title="Detail Registrasi KRS" />

            <div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
                <PageHeader
                    title="Detail Registrasi KRS"
                    actions={
                        backHref && (
                            <Button variant="outline" asChild>
                                <Link href={backHref}>
                                    <ArrowLeft className="h-4 w-4" />
                                    Kembali
                                </Link>
                            </Button>
                        )
                    }
                />

                {semesters.length > 0 && (
                    <Tabs value={currentKey} onValueChange={setActiveSemester}>
                        <TabsList>
                            {semesters.map((semester) => (
                                <TabsTrigger
                                    key={semesterKey(semester)}
                                    value={semesterKey(semester)}
                                >
                                    {semester !== null
                                        ? `Semester ${semester}`
                                        : 'Lainnya'}
                                    {!isSemesterOpenForStudent(
                                        semester,
                                        openSemesters,
                                        studentCurrentSemester,
                                    ) && ' (Ditutup)'}
                                </TabsTrigger>
                            ))}
                        </TabsList>
                    </Tabs>
                )}

                {currentSubmission ? (
                    <SemesterCard
                        key={currentKey}
                        semester={currentSemester}
                        submission={currentSubmission}
                        studentId={studentId}
                        isSemesterOpen={isSemesterOpenForStudent(
                            currentSemester,
                            openSemesters,
                            studentCurrentSemester,
                        )}
                        backHref={backHref}
                        canReview={canReview}
                        canSignAsKaprodi={canSignAsKaprodi}
                        canSignAsAdvisor={canSignAsAdvisor}
                    />
                ) : (
                    semesters.length > 0 &&
                    !hasActiveTerm && (
                        <Card>
                            <CardContent className="flex flex-col items-center gap-2 py-12 text-center">
                                <Inbox className="h-10 w-10 text-muted-foreground" />
                                <p className="font-medium">
                                    Belum ada periode akademik aktif
                                </p>
                                <p className="max-w-sm text-sm text-muted-foreground">
                                    Registrasi KRS hanya dapat dilakukan saat
                                    ada periode akademik yang aktif. Silakan
                                    hubungi admin untuk informasi lebih
                                    lanjut.
                                </p>
                            </CardContent>
                        </Card>
                    )
                )}

                {semesters.length === 0 && (
                    <Card>
                        <CardContent className="flex flex-col items-center gap-2 py-12 text-center">
                            <Inbox className="h-10 w-10 text-muted-foreground" />
                            <p className="font-medium">
                                Belum ada mata kuliah terdaftar
                            </p>
                            <p className="max-w-sm text-sm text-muted-foreground">
                                Belum ada mata kuliah yang terdaftar untuk
                                jurusan ini. Silakan hubungi admin atau
                                program studi.
                            </p>
                        </CardContent>
                    </Card>
                )}
            </div>
        </>
    );
}
