import {
    Dialog,
    DialogContent,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Badge } from '@/components/ui/badge';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import type { FormHistory } from './columns';

type AttributeChangesDialogProps = {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    item: FormHistory | null;
};

const eventBadgeVariant: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {
    created: 'default',
    updated: 'secondary',
    deleted: 'destructive',
};

const eventLabel: Record<string, string> = {
    created: 'Ditambahkan',
    updated: 'Diperbarui',
    deleted: 'Dihapus',
};

function renderValue(key: string, value: unknown): React.ReactNode {
    if (value === null || value === undefined) {
        return <span className="text-muted-foreground">-</span>;
    }

    if (typeof value === 'boolean') {
        return value ? 'Ya' : 'Tidak';
    }

    if (Array.isArray(value)) {
        if (value.length === 0) {
            return <span className="text-muted-foreground">-</span>;
        }

        if (typeof value[0] === 'object' && value[0] !== null) {
            return <RenderObjectArray items={value} />;
        }

        return value.join(', ');
    }

    if (typeof value === 'object') {
        return JSON.stringify(value);
    }

    return String(value);
}

function RenderObjectArray({ items }: { items: Record<string, unknown>[] }) {
    if (!items.length) {
        return <span className="text-muted-foreground">-</span>;
    }

    const keys = Object.keys(items[0]);

    return (
        <div className="rounded-md border">
            <div className="max-h-[300px] overflow-auto">
                <Table>
                    <TableHeader>
                        <TableRow>
                            {keys.map((key) => (
                                <TableHead key={key} className="h-8 text-xs">
                                    {key}
                                </TableHead>
                            ))}
                        </TableRow>
                    </TableHeader>
                    <TableBody>
                        {items.map((item, index) => (
                            <TableRow key={index}>
                                {keys.map((key) => (
                                    <TableCell key={key} className="py-1.5 text-xs">
                                        {renderValue(key, item[key])}
                                    </TableCell>
                                ))}
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>
            </div>
        </div>
    );
}

export function AttributeChangesDialog({ open, onOpenChange, item }: AttributeChangesDialogProps) {
    if (!item) {
        return null;
    }

    const changes = item.attribute_changes;
    const hasNew = changes?.new && Object.keys(changes.new).length > 0;
    const hasOld = changes?.old && Object.keys(changes.old).length > 0;

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-w-3xl overflow-hidden">
                <DialogHeader>
                    <DialogTitle className="flex items-center gap-2">
                        <span>{item.description}</span>
                        <Badge variant={eventBadgeVariant[item.event] ?? 'outline'}>
                            {eventLabel[item.event] ?? item.event}
                        </Badge>
                    </DialogTitle>
                </DialogHeader>

                <div className="space-y-4 overflow-y-auto max-h-[calc(85vh-8rem)]">
                    <div className="text-sm text-muted-foreground space-y-1">
                        <div>Oleh: <span className="font-medium text-foreground">{item.causer?.full_name ?? item.causer?.username ?? '-'}</span></div>
                        <div>{item.formatted_created_at}</div>
                    </div>

                    {hasNew && (
                        <div className="space-y-2">
                            <h4 className="text-sm font-medium">Nilai Baru</h4>
                            <div className="rounded-md border p-3 bg-muted/50">
                                <dl className="space-y-2">
                                    {Object.entries(changes!.new!).map(([key, value]) => (
                                        <div key={key} className="flex flex-col">
                                            <dt className="text-xs text-muted-foreground">{key}</dt>
                                            <dd className="text-sm font-medium">{renderValue(key, value)}</dd>
                                        </div>
                                    ))}
                                </dl>
                            </div>
                        </div>
                    )}

                    {hasOld && (
                        <div className="space-y-2">
                            <h4 className="text-sm font-medium">Nilai Lama</h4>
                            <div className="rounded-md border p-3 bg-muted/50">
                                <dl className="space-y-2">
                                    {Object.entries(changes!.old!).map(([key, value]) => (
                                        <div key={key} className="flex flex-col">
                                            <dt className="text-xs text-muted-foreground">{key}</dt>
                                            <dd className="text-sm font-medium">{renderValue(key, value)}</dd>
                                        </div>
                                    ))}
                                </dl>
                            </div>
                        </div>
                    )}

                    {!hasNew && !hasOld && (
                        <p className="text-sm text-muted-foreground text-center py-4">
                            Tidak ada perubahan data.
                        </p>
                    )}
                </div>
            </DialogContent>
        </Dialog>
    );
}
