import type { Document } from "dbtype";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card.tsx";
import TagBadge, { toPrettyTagname } from "@/components/gallery/TagBadge.tsx";
import { Fragment, useLayoutEffect, useRef, useState } from "react";
import { LazyImage } from "./LazyImage.tsx";
import StyledLink from "./StyledLink.tsx";
import React from "react";
import { Skeleton } from "../ui/skeleton.tsx";
import { Palette, Users, Trash2, Clock, LayersIcon } from "lucide-react";

function clipTagsWhenOverflow(tags: string[], limit: number) {
    let l = 0;
    for (let i = 0; i < tags.length; i++) {
        l += tags[i].length;
        if (l > limit) {
            return tags.slice(0, i);
        }
        l += 1; // for space
    }
    return tags;
}


function GalleryCardImpl({
    doc: x
}: { doc: Document; }) {
    const ref = useRef<HTMLUListElement>(null);
    const [clipCharCount, setClipCharCount] = useState(200);
    const isDeleted = x.deleted_at !== null;

    const artists = x.tags.filter(x => x.startsWith("artist:")).map(x => x.replace("artist:", ""));
    const groups = x.tags.filter(x => x.startsWith("group:")).map(x => x.replace("group:", ""));

    const originalTags = x.tags.filter(x => !x.startsWith("artist:") && !x.startsWith("group:"));
    const clippedTags = clipTagsWhenOverflow(originalTags, clipCharCount);

    useLayoutEffect(() => {
        const listener = () => {
            if (ref.current) {
                const { width } = ref.current.getBoundingClientRect();
                const canvas = document.createElement("canvas");
                const context = canvas.getContext("2d");
                if (context) {
                    // 스타일에 맞는 폰트 설정 (Tailwind의 기본 폰트 스타일에 맞게 설정)
                    context.font = getComputedStyle(ref.current).font || "16px sans-serif";

                    let totalWidth = 0;
                    let charCount = 0;

                    for (const tag of originalTags) {
                        // prefix와 패딩을 고려한 너비 계산
                        const prettyTag = toPrettyTagname(tag); // prefix가 포함된 태그 이름
                        const tagWidth =
                            context.measureText(prettyTag).width + 8; // 양쪽 패딩 4px씩 추가
                        const spaceWidth = context.measureText(" ").width; // 공백 너비

                        if (totalWidth + tagWidth + spaceWidth > width * 3) { // 3줄 제한
                            break;
                        }
                        totalWidth += tagWidth + spaceWidth;
                        charCount += tag.length + 1; // 태그 길이 + 공백
                    }

                    setClipCharCount(charCount);
                }
                else {
                    const charWidth = 7; // rough estimate
                    const newClipCharCount = Math.floor(width / charWidth) * 3;
                    setClipCharCount(newClipCharCount);
                }
            }
        };
        listener();
        window.addEventListener("resize", listener);
        return () => {
            window.removeEventListener("resize", listener);
        };
    }, [originalTags]);

    return <Card className="flex h-[200px] overflow-hidden transition-all duration-200 hover:shadow-lg hover:shadow-primary/20 group">
            {isDeleted ? (
                <div className="bg-gradient-to-br from-red-500/20 to-red-800/30 flex items-center justify-center h-[200px] w-[142px] rounded-l-xl border-r border-border/50">
                    <div className="flex flex-col items-center gap-2 text-primary-foreground">
                        <Trash2 className="h-8 w-8 opacity-80" />
                        <span className="text-sm font-medium">Deleted</span>
                    </div>
                </div>
            ) : (
                <div className="relative rounded-l-xl overflow-hidden h-[200px] w-[142px] flex-none bg-gradient-to-br from-primary/5 to-primary/10 flex items-center justify-center group-hover:from-primary/10 group-hover:to-primary/20 transition-all duration-300">
                    <LazyImage 
                        src={`/api/doc/${x.id}/comic/thumbnail`}
                        alt={x.title}
                        className="max-h-full max-w-full object-cover object-center transition-transform duration-300 group-hover:scale-105"
                    />
                    <div className="absolute bottom-2 right-2 bg-black/70 text-white text-xs px-2 py-1 rounded-full flex items-center gap-1 opacity-80">
                        <LayersIcon className="h-3 w-3" />
                        <span>{x.pagenum}</span>
                    </div>
                </div>
            )}
            
            <div className="flex-1 flex flex-col">
                <CardHeader className="flex-none">
                    <CardTitle className="group-hover:text-primary transition-colors duration-200">
                        <StyledLink className="line-clamp-2 font-bold" to={`/doc/${x.id}`}>
                            {x.title}
                        </StyledLink>
                    </CardTitle>
                    <CardDescription className="flex flex-wrap items-center gap-x-3">
                        {artists.length > 0 && (
                            <div className="flex items-center gap-1.5">
                                <Palette className="h-3.5 w-3.5 text-primary/70" />
                                <span className="flex flex-wrap items-center">
                                    {artists.map((x, i) => (
                                        <Fragment key={`artist:${x}`}>
                                            <StyledLink 
                                                to={`/search?allow_tag=artist:${x}`}
                                                className="hover:text-primary hover:underline transition-colors"
                                            >
                                                {x}
                                            </StyledLink>
                                            {i + 1 < artists.length && <span className="opacity-50 mx-1">,</span>}
                                        </Fragment>
                                    ))}
                                </span>
                            </div>
                        )}
                        
                        {groups.length > 0 && (
                            <div className="flex items-center gap-1.5">
                                <Users className="h-3.5 w-3.5 text-primary/70" />
                                <span className="flex flex-wrap items-center">
                                    {groups.map((x, i) => (
                                        <Fragment key={`group:${x}`}>
                                            <StyledLink 
                                                to={`/search?allow_tag=group:${x}`}
                                                className="hover:text-primary hover:underline transition-colors"
                                            >
                                                {x}
                                            </StyledLink>
                                            {i + 1 < groups.length && <span className="opacity-50 mx-1">,</span>}
                                        </Fragment>
                                    ))}
                                </span>
                            </div>
                        )}
                        
                        <div className="flex items-center gap-1.5 text-muted-foreground">
                            <Clock className="h-3.5 w-3.5" />
                            <span className="text-xs">{new Date(x.created_at).toLocaleDateString()}</span>
                        </div>
                    </CardDescription>
                </CardHeader>
                
                <CardContent className="flex-1 overflow-hidden">
                    <ul ref={ref} className="flex flex-wrap gap-1.5 items-baseline content-start">
                        {clippedTags.map(tag => (
                            <TagBadge 
                                key={tag} 
                                tagname={tag} 
                                className="transition-all duration-200 hover:shadow-sm hover:scale-105" 
                            />
                        ))}
                        {clippedTags.length < originalTags.length && (
                            <TagBadge 
                                key={"..."} 
                                tagname="..." 
                                className="inline-block opacity-70" 
                                disabled 
                            />
                        )}
                    </ul>
                </CardContent>
            </div>
        </Card>
}

export function GalleryCardSkeleton({
    tagCount = 20
}: {
    tagCount?: number;
}) {
    return <Card className="flex h-[200px]">
        <Skeleton className="rounded-xl overflow-hidden h-[200px] w-[142px] flex-none" />
        <div className="flex-1 flex flex-col">
            <CardHeader className="flex-none">
                <Skeleton className="line-clamp-2 w-1/2 h-4" />
                <Skeleton className="w-1/4 h-3" />
            </CardHeader>
            <CardContent className="flex-1 overflow-hidden">
                <ul className="flex flex-wrap gap-2 items-baseline content-start">
                    {Array.from({ length: tagCount }).map((_, i) => <Skeleton key={i}
                        style={{ width: `${Math.random() * 100 + 50}px` }}
                        className="h-4" />)}
                </ul>
            </CardContent>
        </div>
    </Card>
}

export const GalleryCard = React.memo(GalleryCardImpl);