"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";
import Header from "../../components/header";

type SourceType = "twitter" | "pixiv";

type PreviewItem = {
    url: string;
};

type TweetApiResponse = {
    tweet?: {
        author?: { name?: string };
        media?: { photos?: Array<{ url?: string }> };
    };
};

type PixivApiResponse = {
    image_proxy_urls?: string[];
    author_name?: string;
    tags?: string[];
};

type Me = {
    role: "admin" | "writer" | "reader";
};

function detectSource(url: string): SourceType | null {
    if (/^https?:\/\/(www\.)?(x\.com|twitter\.com|fxtwitter\.com|fixupx\.com|vxwitter\.com)\//.test(url)) {
        return "twitter";
    }

    if (/^https?:\/\/(www\.)?pixiv\.net\//.test(url)) {
        return "pixiv";
    }

    return null;
}

function splitTags(text: string) {
    return text
        .split(/[\n,]/)
        .map((tag) => tag.trim().replace(/^#/, ""))
        .filter((tag) => tag.length > 0);
}

export default function AddPage() {
    const [url, setUrl] = useState("");
    const [author, setAuthor] = useState("");
    const [tagsText, setTagsText] = useState("");
    const [previewItems, setPreviewItems] = useState<PreviewItem[]>([]);
    const [selected, setSelected] = useState<boolean[]>([]);
    const [sourceType, setSourceType] = useState<SourceType | null>(null);
    const [loadingPreview, setLoadingPreview] = useState(false);
    const [submitting, setSubmitting] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [success, setSuccess] = useState<string | null>(null);
    const [lastFetchedUrl, setLastFetchedUrl] = useState("");
    const [viewerRole, setViewerRole] = useState<Me["role"] | "guest">("guest");
    const [loadingRole, setLoadingRole] = useState(true);

    const selectedCount = useMemo(
        () => selected.filter(Boolean).length,
        [selected],
    );
    const canPreview = url.trim().length > 0 && !loadingPreview;
    const canSubmit = !submitting && previewItems.length > 0 && selectedCount > 0;
    const tags = useMemo(() => splitTags(tagsText), [tagsText]);
    const sourceLabel = sourceType === "twitter" ? "𝕏" : sourceType === "pixiv" ? "Pixiv" : "-";
    const canManagePost = viewerRole === "admin" || viewerRole === "writer";

    useEffect(() => {
        let active = true;

        async function loadMe() {
            try {
                const response = await fetch("/api/auth/me", { cache: "no-store" });
                if (!response.ok) {
                    if (active) setViewerRole("guest");
                    return;
                }

                const me = (await response.json()) as Me;
                if (active) {
                    setViewerRole(me.role);
                }
            } catch {
                if (active) {
                    setViewerRole("guest");
                }
            } finally {
                if (active) {
                    setLoadingRole(false);
                }
            }
        }

        void loadMe();

        return () => {
            active = false;
        };
    }, []);

    function resetPreview() {
        setPreviewItems([]);
        setSelected([]);
        setSourceType(null);
        setLastFetchedUrl("");
        setError(null);
        setSuccess(null);
    }

    async function fetchPreview(targetUrl?: string) {
        const trimmedUrl = (targetUrl ?? url).trim();
        const source = detectSource(trimmedUrl);
        setError(null);
        setSuccess(null);

        if (!source) {
            setError("지원하지 않는 URL 형식입니다. Twitter(X) 또는 Pixiv URL을 입력해 주세요.");
            return;
        }

        setLoadingPreview(true);
        setSourceType(source);

        try {
            if (source === "twitter") {
                const response = await fetch(`/api/tweet/fetch?url=${encodeURIComponent(trimmedUrl)}`, {
                    cache: "no-store",
                });

                if (!response.ok) {
                    throw new Error(`트위터 미리보기 요청 실패: ${response.status}`);
                }

                const data = (await response.json()) as TweetApiResponse;
                const items = (data.tweet?.media?.photos ?? [])
                    .map((photo) => photo.url)
                    .filter((photoUrl): photoUrl is string => typeof photoUrl === "string" && photoUrl.length > 0)
                    .map((photoUrl) => ({ url: photoUrl }));

                if (items.length === 0) {
                    throw new Error("이미지를 찾지 못했습니다.");
                }

                setPreviewItems(items);
                setSelected(items.map(() => true));
                if (!author.trim()) {
                    setAuthor(data.tweet?.author?.name ?? "");
                }
                setLastFetchedUrl(trimmedUrl);
                return;
            }

            const response = await fetch(`/api/pixiv/fetch?url=${encodeURIComponent(trimmedUrl)}`, {
                cache: "no-store",
            });

            if (!response.ok) {
                throw new Error(`픽시브 미리보기 요청 실패: ${response.status}`);
            }

            const data = (await response.json()) as PixivApiResponse;
            const items = (data.image_proxy_urls ?? [])
                .filter((imageUrl): imageUrl is string => typeof imageUrl === "string" && imageUrl.length > 0)
                .map((imageUrl) => ({ url: imageUrl }));

            if (items.length === 0) {
                throw new Error("이미지를 찾지 못했습니다.");
            }

            setPreviewItems(items);
            setSelected(items.map(() => true));
            if (!author.trim()) {
                setAuthor(data.author_name ?? "");
            }
            if (!tagsText.trim()) {
                const pixivTags = (data.tags ?? []).map((tag) => tag.replace(/^#/, "")).join(", ");
                setTagsText(pixivTags);
            }

            setLastFetchedUrl(trimmedUrl);
        } catch (fetchError) {
            setPreviewItems([]);
            setSelected([]);
            setLastFetchedUrl("");
            setError(fetchError instanceof Error ? fetchError.message : "미리보기를 불러오지 못했습니다.");
        } finally {
            setLoadingPreview(false);
        }
    }

    useEffect(() => {
        if (loadingPreview) {
            return;
        }

        const trimmed = url.trim();
        if (!trimmed || trimmed === lastFetchedUrl) {
            return;
        }

        if (!detectSource(trimmed)) {
            return;
        }

        const timer = window.setTimeout(() => {
            void fetchPreview(trimmed);
        }, 450);

        return () => window.clearTimeout(timer);
    }, [lastFetchedUrl, loadingPreview, url]);

    async function submit(event: FormEvent<HTMLFormElement>) {
        event.preventDefault();
        setError(null);
        setSuccess(null);

        if (!canManagePost) {
            setError("writer 또는 admin 권한이 필요합니다.");
            return;
        }

        if (!sourceType) {
            setError("먼저 미리보기를 불러와 주세요.");
            return;
        }

        if (previewItems.length === 0) {
            setError("업로드할 이미지가 없습니다.");
            return;
        }

        if (selectedCount === 0) {
            setError("최소 한 장 이상 선택해 주세요.");
            return;
        }

        setSubmitting(true);
        try {
            const tags = splitTags(tagsText);
            const response = await fetch("/api/post/upload", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    url: url.trim(),
                    author: author.trim() || undefined,
                    tag: tags.length > 0 ? tags : undefined,
                    selected,
                }),
            });

            if (!response.ok) {
                const responseText = await response.text();
                throw new Error(responseText || `업로드 실패: ${response.status}`);
            }

            const uploadedCount = selectedCount;
            setUrl("");
            setAuthor("");
            setTagsText("");
            resetPreview();
            setSuccess(`${uploadedCount}개 이미지 업로드를 요청했습니다.`);
        } catch (submitError) {
            setError(submitError instanceof Error ? submitError.message : "업로드에 실패했습니다.");
        } finally {
            setSubmitting(false);
        }
    }

    return (
        <div className="min-h-screen bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.9),rgba(247,229,236,0.85)_45%,rgba(244,240,243,1)_100%)] text-foreground">
            <Header />

            <main className="mx-auto w-full max-w-6xl px-4 py-8 sm:px-6 lg:px-8">
                <section className="border-b border-border/70 pb-6">
                    <div className="flex flex-wrap items-start justify-between gap-3">
                        <div>
                            <h1 className="text-xl tracking-wide">Add Post</h1>
                            <p className="mt-1 text-sm text-foreground/50">아래와 같은 유형의 URL을 지원해요!</p>
                            <ul className="text-sm text-foreground/50">
                                <li> - https://x.com, https://twitter.com (기타 FxEmbed URL)</li>
                                <li> - https://pixiv.net (#R-18 태그가 들어갈 시 거부)</li>
                            </ul>
                        </div>
                        <div className="border-l border-border/80 pl-3 text-xs text-foreground/70">
                            <p>Source: <span className="font-medium text-foreground/90">{sourceLabel}</span></p>
                            <p className="mt-0.5">Selected: <span className="font-medium text-foreground/90">{selectedCount}/{previewItems.length}</span></p>
                        </div>
                    </div>

                    <form className="mt-5 space-y-4" onSubmit={submit}>
                        {!loadingRole && !canManagePost ? (
                            <div className="border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
                                업로드 권한이 없습니다. writer 또는 admin 권한이 필요합니다.
                            </div>
                        ) : null}

                        <div className="space-y-2">
                            <label className="block text-sm text-foreground/80" htmlFor="url">URL</label>
                            <div className="flex flex-col gap-2 sm:flex-row">
                                <input
                                    id="url"
                                    type="url"
                                    value={url}
                                    onChange={(event) => {
                                        setUrl(event.target.value);

                                        if (previewItems.length > 0 || sourceType) {
                                            resetPreview();
                                        }
                                    }}
                                    placeholder="https://x.com/... or https://www.pixiv.net/artworks/..."
                                    className="w-full border-b border-border bg-transparent px-2 py-2 text-sm outline-none ring-0 transition focus:border-foreground/40"
                                    disabled={loadingPreview}
                                    required
                                />
                            </div>
                            <p className="text-xs text-foreground/55">URL 변경 시 기존 미리보기는 자동으로 초기화됩니다.</p>
                        </div>

                        <div className="grid gap-4 sm:grid-cols-2">
                            <div className="space-y-2">
                                <label className="block text-sm text-foreground/80" htmlFor="author">작가</label>
                                <input
                                    id="author"
                                    type="text"
                                    value={author}
                                    onChange={(event) => setAuthor(event.target.value)}
                                    className="w-full border-b border-border bg-transparent px-2 py-2 text-sm outline-none transition focus:border-foreground/40"
                                />
                                <p className="text-xs text-red-600/50">* 자동으로 작가를 가져옵니다. 만약 잘못된 이름이라면 수동으로 수정할 수 있습니다.</p>
                            </div>
                            <div className="space-y-2">
                                <label className="block text-sm text-foreground/80" htmlFor="tags">태그</label>
                                <input
                                    id="tags"
                                    type="text"
                                    value={tagsText}
                                    onChange={(event) => setTagsText(event.target.value)}
                                    placeholder=""
                                    className="w-full border-b border-border bg-transparent px-2 py-2 text-sm outline-none transition focus:border-foreground/40"
                                />
                                <p className="text-xs text-foreground/50">* 자동으로 태그를 가져옵니다.  쉼표(,)나 줄바꿈으로 구분하여 여러 개 입력할 수 있습니다.</p>
                            </div>
                        </div>

                        {error ? <p className="text-sm text-red-600">{error}</p> : null}
                        {success ? <p className="text-sm text-emerald-600">{success}</p> : null}

                        {loadingPreview ? (
                            <div className="border-l-2 border-border/80 pl-3 text-xs text-foreground/65">
                                미리보기를 불러오는 중입니다. 이미지 개수에 따라 몇 초 정도 소요될 수 있습니다.
                            </div>
                        ) : null}

                        <div className="flex flex-wrap items-center gap-2 text-xs text-foreground/60">
                            <span>source: {sourceLabel}</span>
                            <span>selected: {selectedCount}/{previewItems.length}</span>
                            <span>tags: {tags.length}</span>
                        </div>

                        {previewItems.length > 0 ? (
                            <section className="mt-8 border-t border-border/70 pt-5">
                                <div className="mb-3 flex items-center justify-between">
                                    <h2 className="text-sm tracking-wide text-foreground/80">Preview</h2>
                                    <div className="flex items-center gap-2 text-xs text-foreground/60">
                                        <span>{selectedCount}장 선택됨</span>
                                        <button
                                            type="button"
                                            className="border border-border px-2 py-1 text-xs text-foreground/70 hover:bg-black/5"
                                            onClick={() => setSelected(previewItems.map(() => true))}
                                        >
                                            전체 선택
                                        </button>
                                        <button
                                            type="button"
                                            className="border border-border px-2 py-1 text-xs text-foreground/70 hover:bg-black/5"
                                            onClick={() => setSelected(previewItems.map(() => false))}
                                        >
                                            전체 해제
                                        </button>
                                    </div>
                                </div>

                                <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
                                    {previewItems.map((item, index) => (
                                        <label
                                            key={`${item.url}-${index}`}
                                            className={`group relative block cursor-pointer overflow-hidden border bg-white/20 transition ${selected[index] ? "border-foreground/35" : "border-border"}`}
                                        >
                                            <img
                                                src={item.url}
                                                alt={`preview ${index + 1}`}
                                                loading="lazy"
                                                decoding="async"
                                                className={`aspect-4/5 w-full object-cover transition ${selected[index] ? "opacity-100" : "opacity-35 grayscale-20"}`}
                                            />
                                            <div className="absolute left-2 top-2 border border-border/60 bg-background/80 px-2 py-1 text-xs backdrop-blur">
                                                <input
                                                    type="checkbox"
                                                    checked={selected[index] ?? false}
                                                    onChange={() => {
                                                        setSelected((current) => current.map((value, i) => (i === index ? !value : value)));
                                                    }}
                                                />
                                            </div>
                                            {selected[index] ? (
                                                <div className="pointer-events-none absolute right-2 top-2 border border-foreground bg-foreground px-2 py-0.5 text-[11px] text-background">
                                                    selected
                                                </div>
                                            ) : null}
                                            <div className="pointer-events-none absolute inset-x-2 bottom-2 truncate border border-white/20 bg-black/65 px-2 py-1 text-xs text-white opacity-0 transition group-hover:opacity-100">
                                                #{index + 1}
                                            </div>
                                        </label>
                                    ))}
                                </div>
                            </section>
                        ) : null}

                        <div className="flex flex-wrap items-center justify-end gap-2">
                            <button
                                type="submit"
                                disabled={!canSubmit || !canManagePost || loadingRole}
                                className="border border-border bg-foreground px-4 py-2 text-sm text-background transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
                            >
                                {submitting ? "업로드 중..." : "업로드"}
                            </button>
                        </div>
                    </form>
                </section>


            </main>
        </div>
    );
}
