import type { FormComponentRef } from '@inertiajs/core';
import { Form, Head, router, usePage } from '@inertiajs/react';
import { ChevronDown, Eye, LogOut, PanelLeftClose, PanelLeftOpen, Send } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { toast, Toaster } from 'sonner';
import { AppSidebar } from '@/components/AppSidebar';
import { Button } from '@/components/ui/button';
import { useAppSidebar } from '@/hooks/useAppSidebar';
import { Checkbox } from '@/components/ui/checkbox';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import {
    Field,
    FieldError,
    FieldGroup,
    FieldLabel,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
    Tooltip,
    TooltipContent,
    TooltipProvider,
    TooltipTrigger,
} from '@/components/ui/tooltip';
import { stripPaginationLabel } from '@/lib/constants';
import { route } from '@/lib/route';
import { cn } from '@/lib/utils';

type DomainOption = {
    id: number;
    account_name: string;
    domain: string;
};

type NotificationRow = {
    id: number;
    message: string;
    domains: string[];
    send_by_name: string;
    date: string;
    time: string;
    created_at: string;
};

type PaginatedNotifications = {
    data: NotificationRow[];
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
    from: number | null;
    to: number | null;
    links: Array<{ url: string | null; label: string; active: boolean }>;
};

function DetailRow({ label, value }: { label: string; value: string }) {
    return (
        <div>
            <p className="text-sm text-muted-foreground">{label}</p>
            <p className="mt-1 text-sm font-medium break-words whitespace-pre-wrap">{value}</p>
        </div>
    );
}

export default function NotificationBroadcast({
    auth,
    domains,
    notifications,
}: {
    auth: { user: { first_name: string; last_name: string; email: string } | null };
    domains: DomainOption[];
    notifications: PaginatedNotifications;
}) {
    const { flash } = usePage().props as {
        flash?: { success?: string | null; error?: string | null };
    };

    const formRef = useRef<FormComponentRef | null>(null);
    const [title, setTitle] = useState('');
    const [message, setMessage] = useState('');
    const [selectedIds, setSelectedIds] = useState<number[]>([]);
    const [domainsOpen, setDomainsOpen] = useState(false);
    const [clientErrors, setClientErrors] = useState<Record<string, string>>({});
    const [viewing, setViewing] = useState<NotificationRow | null>(null);
    const { collapsed: sidebarCollapsed, mobileOpen, toggleSidebar, closeMobile, showOpenIcon } =
        useAppSidebar();

    useEffect(() => {
        if (flash?.success) {
            toast.success(flash.success, { duration: 6000 });
            setTitle('');
            setMessage('');
            setSelectedIds([]);
            setDomainsOpen(false);
            setClientErrors({});
        }
        if (flash?.error) {
            toast.error(flash.error);
        }
    }, [flash?.success, flash?.error]);

    const allSelected = domains.length > 0 && selectedIds.length === domains.length;
    const selectedDomains = domains.filter((domain) => selectedIds.includes(domain.id));
    const domainTriggerLabel =
        selectedDomains.length === 0
            ? 'Select domains'
            : selectedDomains.length === 1
              ? selectedDomains[0].account_name || selectedDomains[0].domain
              : `${selectedDomains.length} domains selected`;
    const requiredFieldsFilled =
        message.trim() !== '' && selectedIds.length > 0 && domains.length > 0;

    function clearDomainError() {
        setClientErrors((prev) => {
            if (!prev.domain_ids) {
                return prev;
            }
            const next = { ...prev };
            delete next.domain_ids;
            return next;
        });
    }

    function toggleDomain(id: number) {
        setSelectedIds((prev) =>
            prev.includes(id) ? prev.filter((value) => value !== id) : [...prev, id],
        );
        clearDomainError();
    }

    function toggleAll() {
        setSelectedIds(allSelected ? [] : domains.map((domain) => domain.id));
        clearDomainError();
    }

    function validateClient(): Record<string, string> {
        const errors: Record<string, string> = {};
        if (!message.trim()) {
            errors.message = 'The message field is required.';
        } else if (message.trim().length > 2000) {
            errors.message = 'The message field must not be greater than 2000 characters.';
        }
        if (selectedIds.length === 0) {
            errors.domain_ids = 'Please select at least one domain.';
        }
        return errors;
    }

    const rows = notifications.data;

    return (
        <>
            <Head title="Notification Broadcast" />
            <Toaster
                position="bottom-right"
                toastOptions={{
                    classNames: {
                        success:
                            '!bg-green-600 !text-white !border-green-700 [&_[data-icon]]:!text-white whitespace-pre-line',
                        error: '!bg-red-600 !text-white !border-red-700 [&_[data-icon]]:!text-white',
                    },
                }}
            />

            <div className="flex h-svh gap-3 overflow-hidden bg-background p-3">
                <AppSidebar
                    auth={auth}
                    collapsed={sidebarCollapsed}
                    mobileOpen={mobileOpen}
                    onMobileClose={closeMobile}
                    active="notification-broadcast"
                />

                <div className="flex min-h-0 min-w-0 flex-1 flex-col gap-3">
                    <header className="flex h-12 shrink-0 items-center justify-between gap-3 rounded-2xl border border-border bg-card px-4 shadow-sm">
                        <div className="flex min-w-0 items-center gap-3">
                            <Button
                                type="button"
                                variant="ghost"
                                size="icon"
                                className="cursor-pointer"
                                aria-label={showOpenIcon ? 'Open sidebar' : 'Close sidebar'}
                                onClick={toggleSidebar}
                            >
                                {showOpenIcon ? (
                                    <PanelLeftOpen className="size-4" aria-hidden />
                                ) : (
                                    <PanelLeftClose className="size-4" aria-hidden />
                                )}
                            </Button>

                            <div className="min-w-0">
                                <div className="truncate text-sm font-semibold">
                                    Notification Broadcast
                                </div>
                            </div>
                        </div>

                        <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            className="h-8 cursor-pointer gap-1.5 text-xs"
                            onClick={() => router.post(route('logout'))}
                        >
                            <LogOut className="size-4" aria-hidden />
                            Sign out
                        </Button>
                    </header>

                    <main className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden rounded-2xl border border-border bg-card px-6 py-4 shadow-sm">
                        <Form
                            ref={formRef}
                            action={route('notification-broadcast.store')}
                            method="post"
                            options={{ preserveScroll: true }}
                            onSubmit={(event) => {
                                const errors = validateClient();
                                if (Object.keys(errors).length > 0) {
                                    event.preventDefault();
                                    setClientErrors(errors);
                                }
                            }}
                            className="shrink-0 rounded-xl border border-border/80 bg-muted/20 p-4"
                        >
                            {({ errors, processing }) => {
                                const titleError = clientErrors.title ?? errors.title;
                                const messageError = clientErrors.message ?? errors.message;
                                const domainError =
                                    clientErrors.domain_ids ??
                                    errors.domain_ids ??
                                    errors['domain_ids.0'];
                                const submitDisabled = processing || !requiredFieldsFilled;
                                const showRequiredTooltip =
                                    !processing && !requiredFieldsFilled;

                                const submitButton = (
                                    <Button
                                        type="submit"
                                        disabled={submitDisabled}
                                        className="h-9 cursor-pointer gap-1.5"
                                    >
                                        <Send className="size-3.5" aria-hidden />
                                        {processing ? 'Sending…' : 'Send notification'}
                                    </Button>
                                );

                                return (
                                    <FieldGroup className="gap-4">
                                        <div className="grid gap-4 lg:grid-cols-2">
                                            <Field data-invalid={titleError ? true : undefined}>
                                                <FieldLabel htmlFor="notif-title">Title</FieldLabel>
                                                <Input
                                                    id="notif-title"
                                                    name="title"
                                                    value={title}
                                                    onChange={(e) => setTitle(e.target.value)}
                                                    placeholder="Optional notification title"
                                                    maxLength={120}
                                                    className="h-9 border-border/80 bg-background shadow-none"
                                                />
                                                {titleError && <FieldError>{titleError}</FieldError>}
                                            </Field>

                                            <Field data-invalid={domainError ? true : undefined}>
                                                <FieldLabel>
                                                    Domains{' '}
                                                    <span className="text-destructive" aria-hidden>
                                                        *
                                                    </span>
                                                </FieldLabel>
                                                {selectedIds.map((id) => (
                                                    <input
                                                        key={id}
                                                        type="hidden"
                                                        name="domain_ids[]"
                                                        value={id}
                                                    />
                                                ))}
                                                <Popover
                                                    open={domainsOpen}
                                                    onOpenChange={setDomainsOpen}
                                                >
                                                    <PopoverTrigger
                                                        render={
                                                            <Button
                                                                type="button"
                                                                variant="outline"
                                                                disabled={domains.length === 0}
                                                                aria-invalid={
                                                                    domainError ? true : undefined
                                                                }
                                                                className={cn(
                                                                    'h-9 w-full justify-between border-border/80 bg-background px-3 text-sm font-normal shadow-none',
                                                                    domainError &&
                                                                        'border-destructive',
                                                                    selectedIds.length === 0 &&
                                                                        'text-muted-foreground',
                                                                )}
                                                            />
                                                        }
                                                    >
                                                        <span className="truncate">
                                                            {domains.length === 0
                                                                ? 'No active domains'
                                                                : domainTriggerLabel}
                                                        </span>
                                                        <ChevronDown
                                                            className={cn(
                                                                'size-3.5 shrink-0 text-muted-foreground transition-transform',
                                                                domainsOpen && 'rotate-180',
                                                            )}
                                                            aria-hidden
                                                        />
                                                    </PopoverTrigger>
                                                    <PopoverContent
                                                        align="start"
                                                        className="w-(--anchor-width) min-w-56 gap-0 p-0"
                                                    >
                                                        <div className="flex items-center justify-between gap-2 border-b border-border/80 px-3 py-2">
                                                            <p className="text-xs font-medium text-muted-foreground">
                                                                Domains
                                                            </p>
                                                            <Button
                                                                type="button"
                                                                variant="ghost"
                                                                size="sm"
                                                                className="h-7 cursor-pointer px-2 text-xs"
                                                                onClick={toggleAll}
                                                            >
                                                                {allSelected
                                                                    ? 'Clear all'
                                                                    : 'Select all'}
                                                            </Button>
                                                        </div>
                                                        <div className="max-h-56 space-y-1 overflow-y-auto p-1.5">
                                                            {domains.map((domain) => {
                                                                const checked =
                                                                    selectedIds.includes(
                                                                        domain.id,
                                                                    );
                                                                const label =
                                                                    domain.account_name ||
                                                                    domain.domain;

                                                                return (
                                                                    <label
                                                                        key={domain.id}
                                                                        className="flex cursor-pointer items-start gap-2.5 rounded-md px-2 py-1.5 text-sm hover:bg-muted/60"
                                                                    >
                                                                        <Checkbox
                                                                            checked={checked}
                                                                            onCheckedChange={() =>
                                                                                toggleDomain(
                                                                                    domain.id,
                                                                                )
                                                                            }
                                                                            className="mt-0.5"
                                                                        />
                                                                        <span className="min-w-0">
                                                                            <span className="font-medium">
                                                                                {label}
                                                                            </span>
                                                                            {domain.account_name !==
                                                                                '' && (
                                                                                <span className="mt-0.5 block truncate text-xs text-muted-foreground">
                                                                                    {domain.domain}
                                                                                </span>
                                                                            )}
                                                                        </span>
                                                                    </label>
                                                                );
                                                            })}
                                                        </div>
                                                    </PopoverContent>
                                                </Popover>
                                                {domainError && (
                                                    <FieldError>{domainError}</FieldError>
                                                )}
                                            </Field>
                                        </div>

                                        <Field data-invalid={messageError ? true : undefined}>
                                            <FieldLabel htmlFor="notif-message">
                                                Message{' '}
                                                <span className="text-destructive" aria-hidden>
                                                    *
                                                </span>
                                            </FieldLabel>
                                            <textarea
                                                id="notif-message"
                                                name="message"
                                                value={message}
                                                onChange={(e) => {
                                                    setMessage(e.target.value);
                                                    setClientErrors((prev) => {
                                                        if (!prev.message) {
                                                            return prev;
                                                        }
                                                        const next = { ...prev };
                                                        delete next.message;
                                                        return next;
                                                    });
                                                }}
                                                rows={4}
                                                maxLength={2000}
                                                placeholder="Write the notification message…"
                                                className={cn(
                                                    'max-h-40 w-full resize-y overflow-y-auto rounded-lg border border-border/80 bg-background px-3 py-2 text-sm shadow-none outline-none',
                                                    'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50',
                                                    messageError &&
                                                        'border-destructive aria-invalid:ring-destructive/20',
                                                )}
                                            />
                                            {messageError && (
                                                <FieldError>{messageError}</FieldError>
                                            )}
                                        </Field>

                                        <div className="flex justify-end">
                                            {showRequiredTooltip ? (
                                                <TooltipProvider>
                                                    <Tooltip>
                                                        <TooltipTrigger
                                                            render={
                                                                <span className="inline-flex" />
                                                            }
                                                        >
                                                            {submitButton}
                                                        </TooltipTrigger>
                                                        <TooltipContent side="top">
                                                            Fill the required fields
                                                        </TooltipContent>
                                                    </Tooltip>
                                                </TooltipProvider>
                                            ) : (
                                                submitButton
                                            )}
                                        </div>
                                    </FieldGroup>
                                );
                            }}
                        </Form>

                        <div className="flex min-h-0 flex-1 flex-col gap-3 overflow-hidden">
                            <div className="shrink-0 text-sm font-semibold">Sent history</div>

                            <div className="min-h-0 flex-1 overflow-auto rounded-xl border border-border/80">
                                <div className="min-w-[640px]">
                                    <div className="sticky top-0 z-10 grid grid-cols-[minmax(0,1.6fr)_minmax(0,0.8fr)_minmax(0,0.9fr)_72px] gap-3 border-b border-border/80 bg-muted/40 px-4 py-2.5 text-xs font-medium text-muted-foreground">
                                        <div>Message</div>
                                        <div>Sent by</div>
                                        <div>Sent at</div>
                                        <div className="text-right">View</div>
                                    </div>

                                    {rows.length === 0 ? (
                                        <div className="px-4 py-10 text-center text-sm text-muted-foreground">
                                            No notifications sent yet.
                                        </div>
                                    ) : (
                                        rows.map((row) => (
                                            <div
                                                key={row.id}
                                                className="grid grid-cols-[minmax(0,1.6fr)_minmax(0,0.8fr)_minmax(0,0.9fr)_72px] gap-3 border-b border-border/60 px-4 py-3 text-sm last:border-b-0"
                                            >
                                                <div className="truncate" title={row.message}>
                                                    {row.message}
                                                </div>
                                                <div className="truncate">{row.send_by_name}</div>
                                                <div className="truncate text-muted-foreground">
                                                    {row.created_at}
                                                </div>
                                                <div className="flex justify-end">
                                                    <Button
                                                        type="button"
                                                        variant="ghost"
                                                        size="icon"
                                                        className="size-8 cursor-pointer"
                                                        aria-label="View notification"
                                                        onClick={() => setViewing(row)}
                                                    >
                                                        <Eye className="size-4" aria-hidden />
                                                    </Button>
                                                </div>
                                            </div>
                                        ))
                                    )}
                                </div>
                            </div>

                            {notifications.last_page > 1 && (
                                <div className="flex shrink-0 flex-wrap items-center justify-between gap-3">
                                    <p className="text-sm text-muted-foreground">
                                        Showing {notifications.from ?? 0}–{notifications.to ?? 0}{' '}
                                        of {notifications.total}
                                    </p>
                                    <nav className="flex flex-wrap gap-1" aria-label="Pagination">
                                        {notifications.links.map((link, index) => {
                                            const label = stripPaginationLabel(link.label);

                                            if (!link.url) {
                                                return (
                                                    <span
                                                        key={`${label}-${index}`}
                                                        className="inline-flex h-8 min-w-8 items-center justify-center rounded-md px-2 text-sm text-muted-foreground"
                                                    >
                                                        {label}
                                                    </span>
                                                );
                                            }

                                            return (
                                                <Button
                                                    key={`${label}-${index}`}
                                                    type="button"
                                                    variant={link.active ? 'default' : 'outline'}
                                                    size="sm"
                                                    className="h-8 min-w-8 cursor-pointer px-2"
                                                    onClick={() =>
                                                        router.get(link.url!, {}, {
                                                            preserveState: true,
                                                            preserveScroll: true,
                                                        })
                                                    }
                                                >
                                                    {label}
                                                </Button>
                                            );
                                        })}
                                    </nav>
                                </div>
                            )}
                        </div>
                    </main>
                </div>
            </div>

            <Dialog open={viewing !== null} onOpenChange={(open) => !open && setViewing(null)}>
                <DialogContent className="gap-0 overflow-hidden p-0 sm:max-w-lg" showCloseButton>
                    <DialogHeader className="-mx-0 rounded-t-xl border-b bg-muted/50 p-4">
                        <DialogTitle className="text-lg font-semibold">
                            Notification details
                        </DialogTitle>
                        <DialogDescription>
                            Sent on {viewing?.created_at ?? '—'}
                        </DialogDescription>
                    </DialogHeader>
                    {viewing && (
                        <div className="space-y-4 p-4">
                            <DetailRow label="Message" value={viewing.message} />
                            <div>
                                <p className="text-sm text-muted-foreground">Domains</p>
                                <div className="mt-1.5 flex flex-wrap gap-1.5">
                                    {viewing.domains.length > 0 ? (
                                        viewing.domains.map((domain, index) => (
                                            <span
                                                key={`${domain}-${index}`}
                                                className="inline-flex items-center rounded-md border border-border/80 bg-muted/60 px-2 py-0.5 text-xs font-medium"
                                            >
                                                {domain}
                                            </span>
                                        ))
                                    ) : (
                                        <span className="text-sm font-medium">—</span>
                                    )}
                                </div>
                            </div>
                            <DetailRow label="Sent by" value={viewing.send_by_name} />
                        </div>
                    )}
                </DialogContent>
            </Dialog>
        </>
    );
}
