import InputError from '@/components/input-error';
import { Button, buttonVariants } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardFooter,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/app-layout';
import { type BreadcrumbItem } from '@/types';
import { Head, Link, useForm } from '@inertiajs/react';
import { Plus, Save, Trash } from 'lucide-react';
import { FormEventHandler } from 'react';
import { toast } from 'sonner';

interface QuestionRuleData {
    id: number;
    attempt_number: number;
    path?: string | null;
    correct_point: number;
    incorrect_point: number;
    correct_interval_days: number;
    incorrect_interval_days: number;
}

type RuleInput = {
    attempt_number: number | string;
    path: string;
    correct_point: number | string;
    incorrect_point: number | string;
    correct_interval_days: number | string;
    incorrect_interval_days: number | string;
};

type RulesForm = {
    rules: RuleInput[];
};

const breadcrumbs: BreadcrumbItem[] = [
    { title: 'Questions', href: '/question' },
    { title: 'Rules', href: '/question-rules' },
];

const emptyRule = (attemptNumber = 1, path = ''): RuleInput => ({
    attempt_number: attemptNumber,
    path,
    correct_point: '',
    incorrect_point: '',
    correct_interval_days: '',
    incorrect_interval_days: '',
});

const defaultRule: RuleInput = {
    attempt_number: 1,
    path: '',
    correct_point: 30,
    incorrect_point: 10,
    correct_interval_days: 10,
    incorrect_interval_days: 10,
};

export default function Rules({ rules }: { rules: QuestionRuleData[] }) {
    const initialRules = rules.length
        ? rules.map((rule) => ({
            attempt_number: rule.attempt_number,
            path: rule.path ?? '',
            correct_point: rule.correct_point,
            incorrect_point: rule.incorrect_point,
            correct_interval_days: rule.correct_interval_days,
            incorrect_interval_days: rule.incorrect_interval_days,
        }))
        : [defaultRule];

    const { data, setData, errors, put, processing } = useForm<RulesForm>({
        rules: initialRules,
    });

    const formatPath = (path: string) => {
        if (!path) {
            return 'Round 1 (New Question)';
        }

        return path
            .split('')
            .map((character) => (character === 'C' ? 'Correct' : 'Incorrect'))
            .join(' -> ');
    };

    const addRound = () => {
        const currentRules = [...data.rules];
        const maxAttempt = Math.max(0, ...currentRules.map((rule) => Number(rule.attempt_number)));
        const newAttempt = maxAttempt + 1;
        const previousRules = currentRules.filter((rule) => Number(rule.attempt_number) === maxAttempt);

        const nextRules: RuleInput[] = [];

        if (!previousRules.length) {
            nextRules.push(emptyRule(newAttempt));
        } else {
            previousRules.forEach((rule) => {
                if (Number(rule.correct_interval_days) > 0) {
                    nextRules.push(emptyRule(newAttempt, `${rule.path}C`));
                }

                if (Number(rule.incorrect_interval_days) > 0) {
                    nextRules.push(emptyRule(newAttempt, `${rule.path}I`));
                }
            });
        }

        if (!nextRules.length) {
            toast.error('No active paths left to branch.');
            return;
        }

        setData('rules', [...currentRules, ...nextRules]);
    };

    const addSingleRule = () => {
        const maxAttempt = Math.max(0, ...data.rules.map((rule) => Number(rule.attempt_number)));
        setData('rules', [...data.rules, emptyRule(maxAttempt + 1)]);
    };

    const removeRule = (index: number) => {
        const nextRules = [...data.rules];
        nextRules.splice(index, 1);
        setData('rules', nextRules.length ? nextRules : [defaultRule]);
    };

    const updateRule = (index: number, field: keyof RuleInput, value: string) => {
        const nextRules = [...data.rules];
        nextRules[index] = {
            ...nextRules[index],
            [field]: value,
        };
        setData('rules', nextRules);
    };

    const submit: FormEventHandler = (event) => {
        event.preventDefault();

        put(route('question-rules.update'), {
            preserveScroll: true,
            onSuccess: () => toast.success('Question rules updated successfully.'),
            onError: () => toast.error('Please check the rule fields.'),
        });
    };

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Question Rules" />

            <div className="m-5">
                <div className="mb-3 flex justify-end">
                    <Link className={buttonVariants({ variant: 'default' })} href={route('question.index')}>
                        Question List
                    </Link>
                </div>

                <form onSubmit={submit}>
                    <Card>
                        <CardHeader>
                            <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
                                <CardTitle>Global Question Rules</CardTitle>
                                <div className="flex flex-wrap gap-2">
                                    <Button type="button" variant="outline" onClick={addSingleRule} disabled={processing}>
                                        <Plus />
                                        Add Rule
                                    </Button>
                                    <Button type="button" variant="outline" onClick={addRound} disabled={processing}>
                                        <Plus />
                                        Add Next Round
                                    </Button>
                                </div>
                            </div>
                        </CardHeader>

                        <CardContent>
                            <InputError message={(errors as any).rules} />

                            <div className="space-y-5">
                                {data.rules.map((rule, index) => {
                                    const correctRetired = Number(rule.correct_interval_days) === 0 && rule.correct_interval_days !== '';
                                    const incorrectRetired = Number(rule.incorrect_interval_days) === 0 && rule.incorrect_interval_days !== '';

                                    return (
                                        <div key={index} className="rounded-md border p-4">
                                            <div className="mb-4 flex flex-col gap-3 border-b pb-3 md:flex-row md:items-start md:justify-between">
                                                <div>
                                                    <div className="text-base font-semibold text-primary">Round {rule.attempt_number || '-'}</div>
                                                    <div className="text-sm text-muted-foreground">{formatPath(rule.path)}</div>
                                                </div>

                                                {data.rules.length > 1 && (
                                                    <Button
                                                        type="button"
                                                        variant="destructive"
                                                        size="sm"
                                                        onClick={() => removeRule(index)}
                                                        disabled={processing}
                                                    >
                                                        <Trash />
                                                        Remove
                                                    </Button>
                                                )}
                                            </div>

                                            <div className="grid gap-4 md:grid-cols-3">
                                                <div className="flex flex-col gap-1.5">
                                                    <Label htmlFor={`rules-${index}-attempt`}>Attempt Number</Label>
                                                    <Input
                                                        id={`rules-${index}-attempt`}
                                                        type="number"
                                                        min={1}
                                                        value={rule.attempt_number}
                                                        onChange={(event) => updateRule(index, 'attempt_number', event.target.value)}
                                                        disabled={processing}
                                                    />
                                                    <InputError message={(errors as any)[`rules.${index}.attempt_number`] as string | undefined} />
                                                </div>

                                                <div className="flex flex-col gap-1.5 md:col-span-2">
                                                    <Label htmlFor={`rules-${index}-path`}>Path</Label>
                                                    <Input
                                                        id={`rules-${index}-path`}
                                                        value={rule.path}
                                                        onChange={(event) => updateRule(index, 'path', event.target.value.toUpperCase())}
                                                        placeholder="Example: C, I, CI"
                                                        disabled={processing}
                                                    />
                                                    <InputError message={(errors as any)[`rules.${index}.path`] as string | undefined} />
                                                </div>
                                            </div>

                                            <div className="mt-4 grid gap-4 md:grid-cols-2">
                                                <div className="rounded-md border border-green-200 bg-green-50 p-4">
                                                    <div className="mb-3 font-medium text-green-800">If Answered Correctly</div>
                                                    <div className="grid gap-3 sm:grid-cols-2">
                                                        <div className="flex flex-col gap-1.5">
                                                            <Label htmlFor={`rules-${index}-correct-point`} className="text-green-700">
                                                                Award Points
                                                            </Label>
                                                            <Input
                                                                id={`rules-${index}-correct-point`}
                                                                type="number"
                                                                value={rule.correct_point}
                                                                onChange={(event) => updateRule(index, 'correct_point', event.target.value)}
                                                                disabled={processing}
                                                            />
                                                            <InputError message={(errors as any)[`rules.${index}.correct_point`] as string | undefined} />
                                                        </div>

                                                        <div className="flex flex-col gap-1.5">
                                                            <Label htmlFor={`rules-${index}-correct-days`} className="text-green-700">
                                                                Interval Days
                                                            </Label>
                                                            <Input
                                                                id={`rules-${index}-correct-days`}
                                                                type="number"
                                                                min={0}
                                                                value={rule.correct_interval_days}
                                                                onChange={(event) => updateRule(index, 'correct_interval_days', event.target.value)}
                                                                disabled={processing}
                                                            />
                                                            {correctRetired && <div className="text-xs font-medium text-red-700">Retired</div>}
                                                            <InputError
                                                                message={(errors as any)[`rules.${index}.correct_interval_days`] as string | undefined}
                                                            />
                                                        </div>
                                                    </div>
                                                </div>

                                                <div className="rounded-md border border-red-200 bg-red-50 p-4">
                                                    <div className="mb-3 font-medium text-red-800">If Answered Incorrectly</div>
                                                    <div className="grid gap-3 sm:grid-cols-2">
                                                        <div className="flex flex-col gap-1.5">
                                                            <Label htmlFor={`rules-${index}-incorrect-point`} className="text-red-700">
                                                                Award Points
                                                            </Label>
                                                            <Input
                                                                id={`rules-${index}-incorrect-point`}
                                                                type="number"
                                                                value={rule.incorrect_point}
                                                                onChange={(event) => updateRule(index, 'incorrect_point', event.target.value)}
                                                                disabled={processing}
                                                            />
                                                            <InputError message={(errors as any)[`rules.${index}.incorrect_point`] as string | undefined} />
                                                        </div>

                                                        <div className="flex flex-col gap-1.5">
                                                            <Label htmlFor={`rules-${index}-incorrect-days`} className="text-red-700">
                                                                Interval Days
                                                            </Label>
                                                            <Input
                                                                id={`rules-${index}-incorrect-days`}
                                                                type="number"
                                                                min={0}
                                                                value={rule.incorrect_interval_days}
                                                                onChange={(event) => updateRule(index, 'incorrect_interval_days', event.target.value)}
                                                                disabled={processing}
                                                            />
                                                            {incorrectRetired && <div className="text-xs font-medium text-red-700">Retired</div>}
                                                            <InputError
                                                                message={(errors as any)[`rules.${index}.incorrect_interval_days`] as string | undefined}
                                                            />
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    );
                                })}
                            </div>
                        </CardContent>

                        <CardFooter className="mt-5 justify-between">
                            <Button type="button" variant="outline" onClick={() => window.history.back()} disabled={processing}>
                                Cancel
                            </Button>
                            <Button type="submit" disabled={processing}>
                                <Save />
                                Save Rules
                            </Button>
                        </CardFooter>
                    </Card>
                </form>
            </div>
        </AppLayout>
    );
}
