"use client";
import React, { useMemo, useCallback } from "react";
import { useTranslations } from "next-intl";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { Form } from "react-compose-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Card, CardContent } from "@/components/ui/card";
import { FormSubmit } from "@/components/form/form-submit";
import { FormReset } from "@/components/form/form-reset";
import { api } from "@/lib/trpc/client";
import type { AppRouterOutput } from "@/lib/trpc/router";
import { PostType, PostTypeHelpers } from "@/config/enums/topic";
import { PostStatusEnum } from "@/config/enums/post-status";
import { DistrictsEnum } from "@/config/enums/districts";
import { PostForm } from "@/components/dashboard/post/post-form";
import { PostSidebarForm } from "@/components/dashboard/post/post-sidebar-form";
import { ReviewTypeEnum } from "@/config/enums/review-type";
import { ProjectStatusEnum } from "@/config/enums/project-status";
import { ProjectTypeEnum } from "@/config/enums/project-type";
import { Button } from "@/components/ui/button";
import { EditorLayout, EditorLayoutContent, EditorLayoutSidebar } from "@/components/layout/editor";
import { MetaTagsSchema } from "@/server/modules/post/types/post-meta-tags.schema";
import { AccessLevel } from "@/config/enums/access-level";
import { Routes } from "@/config/routes";

type Post = NonNullable<AppRouterOutput["posts"]["get"]>;

export const PostFormSchema = z
    .object({
        isSponsored: z.boolean(),
        isPinned: z.boolean(),
        title: z.string(),
        slug: z
            .string()
            .min(1, "Article slug is required")
            .max(100, "Article slug must be less than 100 characters")
            .regex(
                /^[a-zA-Z0-9\s-_]+$/,
                "Article slug can only contain letters, numbers, spaces, hyphens, and underscores"
            )
            .optional(),
        topic: z.nativeEnum(PostType),
        status: z.nativeEnum(PostStatusEnum),
        publishedAt: z.date().optional(),
        authorId: z.string().uuid().nullable(),
        showAuthorPhoto: z.boolean(),
        location: z.nativeEnum(DistrictsEnum).nullable(),
        description: z.string().max(200),
        content: z.any().default({}),
        rating: z.coerce.number().min(0).max(6).optional(),
        previewId: z.string().uuid("Please select an image for the article preview").nullable(),
        postMedia: z
            .array(
                z.object({
                    mediaId: z.string()
                })
            )
            .optional(),
        lat: z.coerce.number().nullable(),
        lng: z.coerce.number().nullable(),
        primaryTagId: z.string().uuid().nullable().optional(),
        tags: z
            .array(
                z.object({
                    tagId: z.string()
                })
            )
            .min(1, "An article must have at least one tag")
            .optional(),
        metaTags: MetaTagsSchema.optional(),
        accessLevel: z.nativeEnum(AccessLevel).optional(),
        vision: z
            .object({
                isChosen: z.boolean(),
                tag: z.string()
            })
            .optional(),
        review: z
            .object({
                name: z.string(),
                type: z.nativeEnum(ReviewTypeEnum),
                premiereAt: z.date().nullable()
            })
            .optional(),
        project: z
            .object({
                status: z.nativeEnum(ProjectStatusEnum),
                type: z.nativeEnum(ProjectTypeEnum),
                function: z.string().nullable().optional(),
                architect: z.string().nullable().optional(),
                developer: z.string().nullable().optional(),
                address: z.string().nullable().optional(),
                buildStartAt: z.date().nullable().optional(),
                buildEndAt: z.date().nullable().optional()
            })
            .optional(),
        projectPosts: z.array(z.object({ postId: z.string().uuid() })).optional(),
        postProjects: z.array(z.object({ projectId: z.string().uuid() })).optional()
    })
    .superRefine((data, ctx) => {
        if (PostTypeHelpers.hasLocation(data.topic) && !data.location) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: "Location is required for this category",
                path: ["location"]
            });
        }

        if (!data.previewId) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: "Please select an image for the article preview",
                path: ["previewId"]
            });
        }
    });

type PostData = z.infer<typeof PostFormSchema>;

type Props = {
    mainProfileId?: string;
} & (
    | {
          mode: "create";
          id?: undefined;
          post?: never;
      }
    | {
          mode: "edit";
          id: string;
          post: Post;
      }
);

export const PostEditor: React.FC<Props> = (props) => {
    const { mode, mainProfileId } = props;
    const router = useRouter();
    const t = useTranslations();

    const { mutateAsync: createPostMutation } = api.posts.create.useMutation({
        onSuccess(post) {
            router.replace(`/dashboard/posts/${post.slug}/edit`);
        },
        onError: (error) => {
            toast.error(error.message || "Post creation failed");
        }
    });

    const { mutateAsync: updatePostMutation } = api.posts.update.useMutation();

    const handleSubmit = useCallback(
        async (data: PostData) => {
            switch (props.mode) {
                case "create":
                    await createPostMutation({
                        data
                    });
                    break;

                case "edit":
                    await updatePostMutation({
                        id: props.id,
                        data
                    });
                    break;
            }
        },
        [createPostMutation, updatePostMutation, props.mode, props.id]
    );

    const viewLink = useMemo(() => {
        return props.mode === "edit" && props.post ? Routes.POST(props.post.topic, props.post.slug) : null;
    }, [props.mode, props.post]);

    const values = useMemo((): PostData => {
        if (props.mode === "edit") {
            return {
                ...props.post,
                primaryTagId: props.post.primaryTagId || undefined,
                rating: props.post.rating || 0,
                accessLevel: props.post.accessLevel,
                vision: props.post.vision !== null ? props.post.vision : undefined,
                review: props.post.review !== null ? props.post.review : undefined,
                project: props.post.project !== null ? props.post.project : undefined
            };
        }

        return {
            title: "",
            previewId: null,
            authorId: mainProfileId,
            showAuthorPhoto: false,
            status: PostStatusEnum.DRAFT,
            publishedAt: new Date(),
            description: "",
            isSponsored: false,
            isPinned: true,
            location: null,
            lat: null,
            lng: null,
            accessLevel: AccessLevel.PUBLIC,
            postMedia: [] as PostData["postMedia"],
            primaryTagId: undefined,
            tags: [] as PostData["tags"],
            metaTags: {
                basic: {
                    title: "[node:title] | [site:name]",
                    description: "[node:field_underrubrik]"
                },
                schemaOrgArticle: {
                    type: "Article",
                    headline: "[node:title]",
                    name: "[node:title]",
                    description: "[node:field_underrubrik]",
                    datePublished: "[node:datePublished]",
                    dateModified: "[node:dateModified]",
                    mainEntityOfPage: "[node:url]",
                    author: {
                        type: "Person",
                        name: "[node:author]"
                    },
                    publisher: {
                        type: "Organization",
                        name: "[site:name]"
                    },
                    image: {
                        url: "[node:image]",
                        width: 800,
                        height: 640
                    },
                    isAccessibleForFree: true,
                    hasPart: {
                        type: "WebPageElement",
                        cssSelector: ""
                    },
                    speakable: {
                        cssSelector: "",
                        xpath: ""
                    }
                },
                openGraph: {
                    type: "article",
                    title: "[node:title]",
                    description: "[node:field_underrubrik]",
                    url: "[node:url]",
                    siteName: "[site:name]",
                    locale: "da_DK",
                    localeAlternate: "",
                    updatedTime: "[node:dateModified]",
                    image: {
                        url: "[node:image]",
                        width: 1200,
                        height: 630
                    },
                    article: {
                        author: "[node:authorUrl]",
                        publishedTime: "[node:datePublished]",
                        modifiedTime: "[node:dateModified]",
                        tag: "[node:tags]"
                    }
                }
            }
        } as PostData;
    }, [props.mode, props.post, mainProfileId]);

    return (
        <Form<PostData>
            className="flex gap-6"
            resolver={zodResolver(PostFormSchema)}
            values={values}
            onSubmit={handleSubmit}
        >
            <EditorLayout>
                <EditorLayoutContent>
                    <PostForm />

                    <div className="flex justify-end px-4 pt-5">
                        <div className="flex gap-2">
                            {viewLink && (
                                <Button asChild variant="secondary">
                                    <Link href={viewLink}>{t("dashboard.post.editor.actions.view")}</Link>
                                </Button>
                            )}
                            {mode === "edit" && (
                                <FormReset asChild>
                                    <Link href="..">{t("dashboard.post.editor.actions.cancel")}</Link>
                                </FormReset>
                            )}
                            <FormSubmit>
                                {mode === "create"
                                    ? t("dashboard.post.editor.actions.create")
                                    : t("dashboard.post.editor.actions.update")}
                            </FormSubmit>
                        </div>
                    </div>
                </EditorLayoutContent>

                <EditorLayoutSidebar>
                    <Card className="mt-5 shadow-none">
                        <CardContent>
                            <PostSidebarForm currentStatus={props.mode === "edit" ? props.post.status : undefined} />
                        </CardContent>
                    </Card>
                </EditorLayoutSidebar>
            </EditorLayout>
        </Form>
    );
};
