import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { StorageFilePreview } from '@/components/employees/storage-file-preview';
import { AppDateInput } from '@/components/ui/app-date-input';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { useLanguage } from '@/contexts/language-context';
import {
    calculateContractTotalAmount,
    calculateInclusiveDaysBetween,
    formatEmployeeJoiningDateOrDash,
    formatMoneyAmountOrDash,
} from '@/lib/dates';
import { normalizeJoiningDateValue } from '@/lib/jalali-picker';
import { isImageFileUrl } from '@/lib/storage-files';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { buildTemporaryEmployeeContractSchema } from '@/validation/schemas';

function ContractFileField({ id, label, hint, accept, error, currentUrl, currentLabel, onChange }) {
    const [pickedPreview, setPickedPreview] = useState(null);

    useEffect(() => {
        return () => {
            if (pickedPreview?.startsWith('blob:')) {
                URL.revokeObjectURL(pickedPreview);
            }
        };
    }, [pickedPreview]);

    function handleChange(e) {
        const file = e.target.files?.[0] ?? null;

        setPickedPreview((prev) => {
            if (prev?.startsWith('blob:')) {
                URL.revokeObjectURL(prev);
            }
            if (file?.type.startsWith('image/')) {
                return URL.createObjectURL(file);
            }
            return null;
        });

        onChange(e);
    }

    const previewUrl =
        pickedPreview ?? (currentUrl && isImageFileUrl(currentUrl) ? currentUrl : null);

    return (
        <div className="space-y-2">
            <Label htmlFor={id}>{label}</Label>
            {previewUrl ? (
                <StorageFilePreview
                    url={previewUrl}
                    alt={label}
                    linkLabel={currentLabel}
                    size="md"
                />
            ) : currentUrl ? (
                <StorageFilePreview
                    url={currentUrl}
                    alt={label}
                    linkLabel={currentLabel}
                    size="md"
                />
            ) : null}
            <Input
                id={id}
                name={id}
                type="file"
                accept={accept}
                className="cursor-pointer text-sm file:me-3 file:rounded-md file:border-0 file:bg-muted file:px-3 file:py-1.5 file:text-sm file:font-medium"
                onChange={handleChange}
            />
            {hint ? <p className="text-muted-foreground text-xs">{hint}</p> : null}
            {error ? <p className="text-destructive text-sm">{error}</p> : null}
        </div>
    );
}

/**
 * @param {object} props
 * @param {'create' | 'edit'} props.mode
 * @param {number} props.employeeId
 * @param {Record<string, string>} props.labels
 * @param {object} [props.contract]
 * @param {string} props.submitUrl
 * @param {'post' | 'put'} props.submitMethod
 * @param {string} props.submitLabel
 * @param {string} props.submittingLabel
 * @param {() => void} [props.onSuccess]
 */
export function TemporaryEmployeeContractForm({
    mode,
    employeeId,
    labels,
    contract,
    submitUrl,
    submitMethod,
    submitLabel,
    submittingLabel,
    onSuccess,
}) {
    const { t, locale } = useLanguage();
    const p = t.temporaryEmployeeContractsPage;
    const a = t.appActions;
    const isEdit = mode === 'edit';
    const [confirmOpen, setConfirmOpen] = useState(false);

    const existingFiles = useMemo(
        () => ({
            contract: Boolean(contract?.contract_url),
        }),
        [contract],
    );

    const schema = useMemo(
        () =>
            buildTemporaryEmployeeContractSchema(t.validation, {
                isEdit,
                existing: existingFiles,
            }),
        [t.validation, isEdit, existingFiles],
    );

    const form = useForm({
        temporary_employee_id: employeeId,
        from_date: contract?.from_date ?? '',
        to_date: contract?.to_date ?? '',
        daily_amount: contract?.daily_amount ?? '',
        contract: null,
    });

    const totalDays = useMemo(
        () =>
            calculateInclusiveDaysBetween(form.data.from_date, form.data.to_date),
        [form.data.from_date, form.data.to_date],
    );

    const totalAmount = useMemo(
        () =>
            calculateContractTotalAmount(
                totalDays,
                form.data.daily_amount === '' ? null : Number(form.data.daily_amount),
            ),
        [totalDays, form.data.daily_amount],
    );

    const docAccept =
        'image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp,application/pdf,.pdf';

    function normalizeDateField(field, value) {
        const normalized = normalizeJoiningDateValue(value);
        if (normalized !== form.data[field]) {
            form.setData(field, normalized);
        }
        return normalized;
    }

    function buildValidatedPayload() {
        const payload = {
            ...form.data,
            from_date: normalizeDateField('from_date', form.data.from_date),
            to_date: normalizeDateField('to_date', form.data.to_date),
        };

        const parsed = schema.safeParse(payload);

        if (!parsed.success) {
            form.setError(zodErrorToFieldMap(parsed.error));
            return null;
        }

        return parsed.data;
    }

    function handleSubmit(e) {
        e.preventDefault();
        form.clearErrors();

        if (!buildValidatedPayload()) {
            return;
        }

        setConfirmOpen(true);
    }

    function commitSubmit() {
        form.clearErrors();

        if (!buildValidatedPayload()) {
            setConfirmOpen(false);
            return;
        }

        const options = {
            forceFormData: true,
            preserveScroll: true,
            onSuccess,
            onError: () => toast.error(a.requestFailed),
        };

        if (submitMethod === 'post') {
            form.post(submitUrl, options);
        } else {
            form.put(submitUrl, options);
        }
    }

    const totalDaysDisplay =
        totalDays != null ? String(totalDays) : '—';
    const totalAmountDisplay = formatMoneyAmountOrDash(totalAmount, locale);

    return (
        <>
            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={isEdit ? p.confirmUpdateTitle : p.confirmCreateTitle}
                description={isEdit ? p.confirmUpdateBody : p.confirmCreateBody}
                confirmLabel={submitLabel}
                cancelLabel={a.cancel}
                processing={form.processing}
                onConfirm={commitSubmit}
            />
            <form
                noValidate
                onSubmit={handleSubmit}
                className="mx-auto flex w-full max-w-3xl flex-col gap-6"
            >
                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionContract}</CardTitle>
                        <CardDescription>{labels.sectionContractHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="grid gap-6 sm:grid-cols-2">
                        {isEdit && contract?.status ? (
                            <div className="space-y-2 sm:col-span-2">
                                <Label>{labels.contractStatus}</Label>
                                <div className="flex flex-col gap-2">
                                    <Badge
                                        variant={
                                            contract.status === 'terminated'
                                                ? 'outline'
                                                : 'secondary'
                                        }
                                        className="w-fit"
                                    >
                                        {contract.status === 'terminated'
                                            ? labels.statusTerminated
                                            : labels.statusActive}
                                    </Badge>
                                    {contract.status === 'terminated' &&
                                    labels.contractStatusTerminatedHint ? (
                                        <p className="text-muted-foreground text-sm">
                                            {labels.contractStatusTerminatedHint}
                                        </p>
                                    ) : null}
                                </div>
                            </div>
                        ) : null}
                        <div className="space-y-2 sm:col-span-1">
                            <Label htmlFor="from_date">{labels.fromDate}</Label>
                            <AppDateInput
                                id="from_date"
                                forceJalali
                                value={form.data.from_date}
                                onChange={(value) => {
                                    form.setData('from_date', value);
                                    if (form.errors.from_date) {
                                        form.clearErrors('from_date');
                                    }
                                }}
                                invalid={Boolean(form.errors.from_date)}
                            />
                            {form.errors.from_date ? (
                                <p className="text-destructive text-sm">{form.errors.from_date}</p>
                            ) : null}
                            {form.data.from_date ? (
                                <p className="text-muted-foreground text-xs">
                                    {formatEmployeeJoiningDateOrDash(form.data.from_date)}
                                </p>
                            ) : null}
                        </div>
                        <div className="space-y-2 sm:col-span-1">
                            <Label htmlFor="to_date">{labels.toDate}</Label>
                            <AppDateInput
                                id="to_date"
                                forceJalali
                                value={form.data.to_date}
                                onChange={(value) => {
                                    form.setData('to_date', value);
                                    if (form.errors.to_date) {
                                        form.clearErrors('to_date');
                                    }
                                }}
                                invalid={Boolean(form.errors.to_date)}
                            />
                            {form.errors.to_date ? (
                                <p className="text-destructive text-sm">{form.errors.to_date}</p>
                            ) : null}
                            {form.data.to_date ? (
                                <p className="text-muted-foreground text-xs">
                                    {formatEmployeeJoiningDateOrDash(form.data.to_date)}
                                </p>
                            ) : null}
                        </div>
                        <ContractFileField
                            id="contract"
                            label={labels.contractFile}
                            hint={labels.contractFileHint}
                            accept={docAccept}
                            error={form.errors.contract}
                            currentUrl={contract?.contract_url}
                            currentLabel={labels.viewCurrentFile}
                            onChange={(e) => {
                                form.setData('contract', e.target.files?.[0] ?? null);
                                if (form.errors.contract) {
                                    form.clearErrors('contract');
                                }
                            }}
                        />
                        {isEdit && contract?.is_terminated && !contract?.is_paid ? (
                            <div className="rounded-lg border border-amber-500/40 bg-amber-500/5 p-4 sm:col-span-2">
                                <p className="text-sm font-medium">{labels.paymentAfterTerminationTitle}</p>
                                <p className="text-muted-foreground mt-1 text-sm">
                                    {labels.paymentAfterTerminationHint}
                                </p>
                            </div>
                        ) : null}
                        {isEdit && contract?.is_paid ? (
                            <div className="flex items-center gap-2 sm:col-span-2">
                                <Badge variant="secondary">{labels.paidYes}</Badge>
                                {contract.has_fingerprint ? (
                                    <span className="text-muted-foreground text-sm">
                                        {labels.paymentRecordedWithFingerprint}
                                    </span>
                                ) : null}
                            </div>
                        ) : null}
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionAmounts}</CardTitle>
                        <CardDescription>{labels.sectionAmountsHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="grid gap-6 sm:grid-cols-2">
                        <div className="space-y-2">
                            <Label htmlFor="total_days">{labels.totalDays}</Label>
                            <Input
                                id="total_days"
                                readOnly
                                value={totalDaysDisplay}
                                className="bg-muted/50 tabular-nums"
                            />
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="daily_amount">{labels.dailyAmount}</Label>
                            <Input
                                id="daily_amount"
                                name="daily_amount"
                                type="number"
                                min="0"
                                step="0.01"
                                inputMode="decimal"
                                value={form.data.daily_amount}
                                onChange={(e) => {
                                    form.setData('daily_amount', e.target.value);
                                    if (form.errors.daily_amount) {
                                        form.clearErrors('daily_amount');
                                    }
                                }}
                                className="tabular-nums"
                            />
                            {form.errors.daily_amount ? (
                                <p className="text-destructive text-sm">
                                    {form.errors.daily_amount}
                                </p>
                            ) : null}
                        </div>
                        <div className="space-y-2 sm:col-span-2">
                            <Label htmlFor="total_amount">{labels.totalAmount}</Label>
                            <Input
                                id="total_amount"
                                readOnly
                                value={totalAmountDisplay}
                                className="bg-muted/50 tabular-nums"
                            />
                        </div>
                    </CardContent>
                </Card>

                <div className="flex justify-end">
                    <Button type="submit" disabled={form.processing}>
                        {form.processing ? (
                            <>
                                <Spinner className="size-4" />
                                {submittingLabel}
                            </>
                        ) : (
                            submitLabel
                        )}
                    </Button>
                </div>
            </form>
        </>
    );
}
