import React, { useState, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { ColumnDef } from '@tanstack/react-table';
import { Link, useNavigate } from 'react-router-dom';
import { Info, Pencil } from 'lucide-react';
import { useForm, Controller } from 'react-hook-form';
import {
    useReviews,
    useUpdateReview,
    useBulkUpdateReviews,
    useReview,
    useReviewStats,
} from '@/hooks/useReviews';
import { useExploreView } from '@/hooks/useExploreView';
import { useUser } from '@/hooks/useUsers';
import { useEvent } from '@/hooks/useEvents';
import { Review, ReviewListParams } from '@/types/api';
import { getSavedPageSize } from '@/utils/tablePagination';
import { formatStatusLabel } from '@/utils/statusLabels';
import { notify } from '@/lib/notify';
import { ExploreListShell } from '@/components/explore/ExploreListShell';
import { ExploreDataView } from '@/components/explore/ExploreDataView';
import { ExploreInsightsCollapse } from '@/components/explore/ExploreInsightsCollapse';
import { RowActionsMenu, type RowAction } from '@/components/explore/RowActionsMenu';
import type { DenseRowModel } from '@/components/explore/DenseRowList';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Badge } from '@/components/ui/badge';
import {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Skeleton } from '@/components/ui/skeleton';

const TABLE_KEY = 'reviews';

const typeBadgeVariant = (type: string) => {
    if (type === 'calendar') return 'success' as const;
    if (type === 'event') return 'default' as const;
    if (type === 'review') return 'secondary' as const;
    return 'outline' as const;
};

const statusBadgeVariant = (status: string) => {
    if (status === 'visible') return 'success' as const;
    if (status === 'hidden') return 'warning' as const;
    return 'destructive' as const;
};

const isBadValue = (val: unknown) =>
    val === '-' || val === 'undefined' || val === '' || val === null || val === undefined;

interface EditFormValues {
    status: string;
    reason?: string;
    comment?: string;
    rating?: number;
}

interface BulkStatusFormValues {
    reason?: string;
}

function reviewActions(
    handlers: { onOpen: () => void; onEdit: () => void },
    t: TFunction
): RowAction[] {
    return [
        { label: t('common.open'), icon: <Info className="h-4 w-4" />, onClick: handlers.onOpen },
        { label: t('common.edit'), icon: <Pencil className="h-4 w-4" />, onClick: handlers.onEdit },
    ];
}

const UserCell: React.FC<{ userId: string }> = ({ userId }) => {
    const { data: user, isLoading: loading } = useUser(userId);
    if (loading) return <Skeleton className="h-4 w-24" />;
    if (!user) return <span>{userId}</span>;

    const isGoodString = (val: unknown): val is string => !isBadValue(val);
    let name = '';
    if (isGoodString(user.nickname)) {
        name = user.nickname;
    } else if (isGoodString(user.email)) {
        name = user.email;
    } else {
        name = user.id;
    }
    return <Link to={`/users/${user.id}`}>{name}</Link>;
};

const TargetCell: React.FC<{ targetType: string; targetId: string }> = ({ targetType, targetId }) => {
    const { data: event, isLoading: loading } = useEvent(targetType === 'event' ? targetId : '');
    if (targetType === 'event') {
        if (loading) return <Skeleton className="h-4 w-24" />;
        if (event) {
            const name = event.title || event.id;
            return <Link to={`/events/${event.id}`}>{name}</Link>;
        }
        return <span>{targetId}</span>;
    }
    return <span>{targetId}</span>;
};

const ReviewListPage: React.FC = () => {
    const { t } = useTranslation();
    const navigate = useNavigate();
    const { viewMode, setViewMode } = useExploreView();
    const [params, setParams] = useState<ReviewListParams>({
        limit: getSavedPageSize(TABLE_KEY),
        offset: 0,
        sort: 'created_at',
        order: 'desc',
    });
    const { data, isLoading } = useReviews(params);
    const { data: stats } = useReviewStats();
    const updateReview = useUpdateReview();
    const bulkUpdate = useBulkUpdateReviews();
    const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);

    const [editModal, setEditModal] = useState<{ open: boolean; reviewId: string | null }>({
        open: false,
        reviewId: null,
    });
    const { data: editingReview, isLoading: loadingReview } = useReview(editModal.reviewId || '');
    const editForm = useForm<EditFormValues>();

    const [bulkStatusModal, setBulkStatusModal] = useState<{ open: boolean; status: string }>({
        open: false,
        status: 'hidden',
    });
    const bulkStatusForm = useForm<BulkStatusFormValues>();

    const pageIds = useMemo(() => (data?.data ?? []).map((r) => r.id), [data?.data]);
    const allPageSelected = pageIds.length > 0 && pageIds.every((id) => selectedRowKeys.includes(id));

    const toggleSelectAll = () => {
        if (allPageSelected) {
            setSelectedRowKeys((prev) => prev.filter((id) => !pageIds.includes(id)));
        } else {
            setSelectedRowKeys((prev) => [...new Set([...prev, ...pageIds])]);
        }
    };

    const toggleRow = (id: string) => {
        setSelectedRowKeys((prev) =>
            prev.includes(id) ? prev.filter((k) => k !== id) : [...prev, id]
        );
    };

    const handleEdit = (id: string) => setEditModal({ open: true, reviewId: id });

    const handleSaveEdit = editForm.handleSubmit((values) => {
        if (!editModal.reviewId) return;
        const status = values.status;
        if ((status === 'hidden' || status === 'deleted') && !values.reason?.trim()) {
            editForm.setError('reason', { message: t('reviews.reasonRequired') });
            return;
        }
        const payload = Object.fromEntries(
            Object.entries(values).filter(([_, v]) => v !== '' && v !== undefined && v !== null)
        );
        updateReview.mutate(
            { id: editModal.reviewId, data: payload },
            { onSuccess: () => setEditModal({ open: false, reviewId: null }) }
        );
    });

    useEffect(() => {
        if (editingReview && editModal.open) {
            editForm.reset({
                status: editingReview.status,
                reason: editingReview.reason ?? undefined,
                comment: editingReview.comment ?? undefined,
                rating: editingReview.rating,
            });
        }
    }, [editingReview, editModal.open, editForm]);

    const openBulkStatusModal = (status: string) => {
        if (selectedRowKeys.length === 0) {
            notify.info(t('reviews.selectReviews'));
            return;
        }
        setBulkStatusModal({ open: true, status });
        bulkStatusForm.reset();
    };

    const handleBulkStatusSubmit = bulkStatusForm.handleSubmit((values) => {
        const reasonRequired =
            bulkStatusModal.status === 'hidden' || bulkStatusModal.status === 'deleted';
        if (reasonRequired && !values.reason?.trim()) {
            bulkStatusForm.setError('reason', { message: t('reviews.reasonRequiredShort') });
            return;
        }
        const reason = values.reason ? values.reason.trim() : '';
        const updates = selectedRowKeys.map((id) => ({
            id,
            status: bulkStatusModal.status,
            reason: reason || undefined,
        }));
        bulkUpdate.mutate(updates, {
            onSuccess: () => {
                setBulkStatusModal({ open: false, status: 'hidden' });
                setSelectedRowKeys([]);
            },
        });
    });

    const exploreStats = useMemo(() => {
        if (!stats) return [];
        const items = [{ label: t('common.total'), value: stats.total_reviews }];
        Object.entries(stats.reviews_by_status || {})
            .slice(0, 3)
            .forEach(([status, count]) => {
                items.push({ label: formatStatusLabel(status), value: count });
            });
        return items.slice(0, 4);
    }, [stats, t]);

    const columns = useMemo<ColumnDef<Review>[]>(
        () => [
            {
                id: 'select',
                header: () => (
                    <input
                        type="checkbox"
                        className="h-4 w-4 rounded border"
                        checked={allPageSelected}
                        onChange={toggleSelectAll}
                        aria-label={t('reviews.selectAllAria')}
                    />
                ),
                size: 40,
                enableSorting: false,
                cell: ({ row }) => (
                    <input
                        type="checkbox"
                        data-testid={`review-check-${row.original.id}`}
                        className="h-4 w-4 rounded border"
                        checked={selectedRowKeys.includes(row.original.id)}
                        onChange={() => toggleRow(row.original.id)}
                        aria-label={t('reviews.selectReviewAria', { id: row.original.id })}
                    />
                ),
            },
            {
                id: 'user',
                header: t('common.user'),
                enableSorting: false,
                cell: ({ row }) => <UserCell userId={row.original.user_id} />,
            },
            {
                accessorKey: 'target_type',
                header: t('common.type'),
                enableSorting: true,
                cell: ({ getValue }) => {
                    const type = getValue<string>();
                    return <Badge variant={typeBadgeVariant(type)}>{type}</Badge>;
                },
            },
            {
                id: 'target',
                header: t('common.target'),
                enableSorting: false,
                cell: ({ row }) => (
                    <TargetCell targetType={row.original.target_type} targetId={row.original.target_id} />
                ),
            },
            {
                accessorKey: 'rating',
                header: t('reviews.score'),
                enableSorting: true,
                cell: ({ getValue }) => '⭐'.repeat(getValue<number>()),
            },
            {
                accessorKey: 'comment',
                header: t('common.comment'),
                enableSorting: false,
                cell: ({ getValue }) => {
                    const comment = getValue<string>();
                    return <span className="line-clamp-2">{comment}</span>;
                },
            },
            {
                accessorKey: 'status',
                header: t('common.status'),
                enableSorting: true,
                cell: ({ getValue }) => {
                    const status = getValue<string>();
                    return <Badge variant={statusBadgeVariant(status)}>{formatStatusLabel(status)}</Badge>;
                },
            },
            {
                id: 'likes',
                header: t('reviews.likesDislikes'),
                enableSorting: false,
                cell: ({ row }) => {
                    const likes = isBadValue(row.original.likes) ? 0 : row.original.likes;
                    const dislikes = isBadValue(row.original.dislikes) ? 0 : row.original.dislikes;
                    return `${likes} / ${dislikes}`;
                },
            },
            {
                id: 'actions',
                header: '',
                size: 48,
                enableSorting: false,
                cell: ({ row }) => {
                    const record = row.original;
                    return (
                        <RowActionsMenu
                            actions={reviewActions({
                                onOpen: () => navigate(`/reviews/${record.id}`),
                                onEdit: () => handleEdit(record.id),
                            }, t)}
                        />
                    );
                },
            },
        ],
        [allPageSelected, selectedRowKeys, navigate, t]
    );

    const denseRows = useMemo<DenseRowModel[]>(() => {
        return (data?.data ?? []).map((record) => {
            const likes = isBadValue(record.likes) ? 0 : record.likes;
            const dislikes = isBadValue(record.dislikes) ? 0 : record.dislikes;
            const title = record.comment
                ? record.comment.length > 60
                    ? `${record.comment.slice(0, 60)}…`
                    : record.comment
                : t('reviews.ratingValue', { rating: record.rating });
            return {
                id: record.id,
                title,
                subtitle: `${record.target_type} · ${record.target_id}`,
                badges: (
                    <>
                        <Badge variant={typeBadgeVariant(record.target_type)}>{record.target_type}</Badge>
                        <Badge variant={statusBadgeVariant(record.status)}>
                            {formatStatusLabel(record.status)}
                        </Badge>
                        <span className="text-xs">{'⭐'.repeat(record.rating)}</span>
                    </>
                ),
                meta: `${likes} / ${dislikes}`,
                actions: reviewActions({
                    onOpen: () => navigate(`/reviews/${record.id}`),
                    onEdit: () => handleEdit(record.id),
                }, t),
            };
        });
    }, [data?.data, navigate, t]);

    return (
        <>
            <ExploreListShell
                data-testid="page-reviews"
                title={t('reviews.title')}
                stats={exploreStats}
                viewMode={viewMode}
                onViewModeChange={setViewMode}
            >
                {stats && (
                    <ExploreInsightsCollapse
                        title={t('explore.tops')}
                        tabs={[
                            {
                                id: 'all',
                                label: t('explore.allReviews'),
                                rows: (stats.top_targets_by_reviews ?? []).map((item) => ({
                                    id: `${item.target_type}-${item.target_id}`,
                                    primary: (
                                        <Link to={`/${item.target_type}s/${item.target_id}`}>{item.target_id}</Link>
                                    ),
                                    secondary: item.target_type,
                                    value: item.review_count,
                                })),
                            },
                            {
                                id: 'positive',
                                label: t('explore.positive'),
                                rows: (stats.top_targets_by_positive_reviews ?? []).map((item) => ({
                                    id: `${item.target_type}-${item.target_id}`,
                                    primary: (
                                        <Link to={`/${item.target_type}s/${item.target_id}`}>{item.target_id}</Link>
                                    ),
                                    secondary: item.target_type,
                                    value: item.review_count,
                                })),
                            },
                            {
                                id: 'negative',
                                label: t('explore.negative'),
                                rows: (stats.top_targets_by_negative_reviews ?? []).map((item) => ({
                                    id: `${item.target_type}-${item.target_id}`,
                                    primary: (
                                        <Link to={`/${item.target_type}s/${item.target_id}`}>{item.target_id}</Link>
                                    ),
                                    secondary: item.target_type,
                                    value: item.review_count,
                                })),
                            },
                        ]}
                    />
                )}

                <div className="flex flex-wrap gap-2">
                    <Button
                        data-testid="btn-reviews-bulk-hidden"
                        variant="outline"
                        onClick={() => openBulkStatusModal('hidden')}
                        disabled={selectedRowKeys.length === 0}
                    >
                        {t('reviews.hideSelected')}
                    </Button>
                    <Button
                        data-testid="btn-reviews-bulk-visible"
                        variant="outline"
                        onClick={() => openBulkStatusModal('visible')}
                        disabled={selectedRowKeys.length === 0}
                    >
                        {t('reviews.showSelected')}
                    </Button>
                    <Button
                        data-testid="btn-reviews-bulk-deleted"
                        variant="destructive"
                        onClick={() => openBulkStatusModal('deleted')}
                        disabled={selectedRowKeys.length === 0}
                    >
                        {t('reviews.deleteSelected')}
                    </Button>
                </div>

                <ExploreDataView
                    viewMode={viewMode}
                    columns={columns}
                    data={data?.data ?? []}
                    denseRows={denseRows}
                    total={data?.total}
                    isLoading={isLoading}
                    tableKey={TABLE_KEY}
                    params={params}
                    onParamsChange={setParams}
                />
            </ExploreListShell>

            <Dialog
                open={editModal.open}
                onOpenChange={(open) => !open && setEditModal({ open: false, reviewId: null })}
            >
                <DialogContent>
                    <DialogHeader>
                        <DialogTitle>{t('reviews.editTitle')}</DialogTitle>
                    </DialogHeader>
                    {loadingReview ? (
                        <div className="space-y-3 py-4">
                            <Skeleton className="h-9 w-full" />
                            <Skeleton className="h-9 w-full" />
                        </div>
                    ) : (
                        <form id="edit-review-form" className="space-y-4" onSubmit={handleSaveEdit}>
                            <div className="space-y-2">
                                <Label>{t('reviews.score')}</Label>
                                <Input
                                    type="number"
                                    min={1}
                                    max={5}
                                    {...editForm.register('rating', { valueAsNumber: true })}
                                />
                            </div>
                            <div className="space-y-2">
                                <Label>{t('common.comment')}</Label>
                                <Textarea rows={3} {...editForm.register('comment')} />
                            </div>
                            <div className="space-y-2">
                                <Label>{t('common.status')}</Label>
                                <Controller
                                    name="status"
                                    control={editForm.control}
                                    render={({ field }) => (
                                        <Select value={field.value} onValueChange={field.onChange}>
                                            <SelectTrigger>
                                                <SelectValue placeholder={t('common.selectStatus')} />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectItem value="visible">visible</SelectItem>
                                                <SelectItem value="hidden">hidden</SelectItem>
                                                <SelectItem value="deleted">deleted</SelectItem>
                                            </SelectContent>
                                        </Select>
                                    )}
                                />
                            </div>
                            <div className="space-y-2">
                                <Label>{t('common.reason')}</Label>
                                <Textarea rows={2} {...editForm.register('reason')} />
                                {editForm.formState.errors.reason && (
                                    <p className="text-sm text-destructive">
                                        {editForm.formState.errors.reason.message}
                                    </p>
                                )}
                            </div>
                        </form>
                    )}
                    <DialogFooter>
                        <Button variant="outline" onClick={() => setEditModal({ open: false, reviewId: null })}>
                            {t('common.cancel')}
                        </Button>
                        <Button type="submit" form="edit-review-form" disabled={updateReview.isPending}>
                            {t('common.save')}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>

            <Dialog
                open={bulkStatusModal.open}
                onOpenChange={(open) => !open && setBulkStatusModal({ open: false, status: 'hidden' })}
            >
                <DialogContent data-testid="dialog-reviews-bulk-status">
                    <DialogHeader>
                        <DialogTitle>
                            {t('reviews.bulkStatusTitle', {
                                status: bulkStatusModal.status,
                                count: selectedRowKeys.length,
                            })}
                        </DialogTitle>
                    </DialogHeader>
                    <form id="bulk-status-form" className="space-y-4" onSubmit={handleBulkStatusSubmit}>
                        <div className="space-y-2">
                            <Label>{t('common.reason')}</Label>
                            <Textarea
                                data-testid="input-bulk-reason"
                                rows={3}
                                placeholder={t('reviews.bulkReasonPlaceholder')}
                                {...bulkStatusForm.register('reason')}
                            />
                            {bulkStatusForm.formState.errors.reason && (
                                <p className="text-sm text-destructive">
                                    {bulkStatusForm.formState.errors.reason.message}
                                </p>
                            )}
                        </div>
                    </form>
                    <DialogFooter>
                        <Button
                            variant="outline"
                            onClick={() => setBulkStatusModal({ open: false, status: 'hidden' })}
                        >
                            {t('common.cancel')}
                        </Button>
                        <Button
                            type="submit"
                            form="bulk-status-form"
                            data-testid="btn-save"
                            disabled={bulkUpdate.isPending}
                        >                            {t('common.apply')}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </>
    );
};

export default ReviewListPage;
