"use client";
import type { PhotoData } from "@/server/api/routers/photos/list";
import { api } from "@/trpc/react";
import Image from "next/image";
import type React from "react";
import { useState } from "react";
import ImageSvg from "./file-svg";
import DirSvg from "./dir-svg";
import { Controller, useForm } from "react-hook-form";

import { zodResolver } from "@hookform/resolvers/zod";
import z from "zod";
import Tiptap from "./photo-editor";

const FormSchema = z.object({
	title: z
		.string()
		.min(3, "Title should be over 3 characters")
		.max(128, "Title cannot be over 128 characters"),
	description: z.object({
		type: z.string(),
		content: z.array(z.unknown()),
	}),
});

type IFormInput = z.infer<typeof FormSchema>;

interface DirectoryTree {
	[key: string]: DirectoryTree;
}

function buildDirectoryTree(filePaths: string[]): DirectoryTree {
	const root: DirectoryTree = {};

	filePaths.forEach((path) => {
		const parts = path.split("/").filter((p) => p.length > 0);
		let current = root;

		// Traverse or create nodes for each part of the path
		for (let i = 0; i < parts.length; i++) {
			const part = parts[i];
			if (part) {
				if (!current[part]) {
					current[part] = {};
				}
				current = current[part];
			}
		}
	});

	return root;
}

type Item = {
	type: "directory" | "file";
	name: string;
	fullPath: string;
	children?: Item[];
};

function renderTree(node: DirectoryTree, pathSoFar = ""): Item[] {
	const entries = Object.entries(node);
	const items: Item[] = [];

	for (const [name, children] of entries) {
		const fullPath = pathSoFar ? `${pathSoFar}/${name}` : name;
		const isLeaf = Object.keys(children).length === 0;

		if (isLeaf) {
			// It's a file
			items.push({ type: "file", name, fullPath });
		} else {
			// It's a directory
			items.push({
				type: "directory",
				name,
				fullPath,
				children: renderTree(children, fullPath),
			});
		}
	}

	return items;
}

function RenderLeaf(leaf: Item[], selectImageTab: (path: string) => void) {
	return leaf.map((leaf) => {
		if (leaf.children?.length) {
			return (
				<li>
					<details open>
						<summary>
							<DirSvg />
							{leaf.name}
						</summary>
						<ul>{RenderLeaf(leaf.children, selectImageTab)}</ul>
					</details>
				</li>
			);
		}
		return (
			<li key={leaf.fullPath}>
				<button type="button" onClick={() => selectImageTab(leaf.fullPath)}>
					<ImageSvg />
					{leaf.name}
				</button>
			</li>
		);
	});
}

export function PhotoTab(): React.JSX.Element {
	const [selectedImage, setSelectedImage] = useState<PhotoData>();
	const query = api.photos.list.useQuery(undefined, {
		refetchOnWindowFocus: false,
	});

	const {
		register,
		handleSubmit,
		control,
		formState: { errors },
	} = useForm<IFormInput>({
		resolver: zodResolver(FormSchema),
		mode: "onSubmit",
	});

	if (query.isLoading) {
		return <p>Loading</p>;
	}
	if (query.error) {
		return <p>{query.error.message}</p>;
	}
	const images = query.data?.data;
	if (!images || images?.length === 0) {
		return <p>No Images</p>;
	}

	const selectImageTab = (path: string) => {
		const img = images.find(
			(img) =>
				img.src === `https://fly.storage.tigris.dev/joemonk-photos/${path}`,
		);
		setSelectedImage(img);
	};

	const tree = buildDirectoryTree(
		images.map((img) =>
			img.src.substring(
				"https://fly.storage.tigris.dev/joemonk-photos/".length,
			),
		),
	);
	const renderedTree = renderTree(tree);

	const onSubmit = (data: IFormInput) => {
		console.log(data);
	};

	return (
		<div className="flex w-full gap-2">
			<ul className="menu menu-xs bg-base-200 box w-1/4">
				{RenderLeaf(renderedTree, selectImageTab)}
			</ul>
			<div className="w-3/4 box border border-base-300 p-2">
				{selectedImage?.src ? (
					<form onSubmit={handleSubmit(onSubmit)}>
						<label
							className={`floating-label input text-lg mb-2 w-full ${errors.title ? "input-error" : null}`}
						>
							<span>{`Title ${errors.title ? " - " + errors.title.message : ""}`}</span>
							<input
								{...register("title")}
								type="text"
								placeholder="Title"
								defaultValue={selectedImage?.title}
							/>
						</label>
						<Image
							src={selectedImage.src}
							title={selectedImage?.title}
							alt={selectedImage?.title ?? "Image to modify data for"}
							width={selectedImage.width}
							height={selectedImage.height}
							blurDataURL={selectedImage.blur}
							placeholder="blur"
						/>
						<div className="mt-2 grid grid-cols-3">
							{[
								{
									title: "F-Stop",
									value: selectedImage.exif.fNumber?.toString(),
								},
								{
									title: "ISO",
									value: selectedImage.exif.isoSpeedRatings?.toString(),
								},
								{
									title: "Exposure",
									value: selectedImage.exif.exposureBiasValue?.toString(),
								},
							].map((setting) => {
								return (
									<div key={setting.title} className="w-full border">
										<span className="px-2 w-20 inline-block">
											{setting.title}
										</span>
										<span className="px-2">{setting.value}</span>
									</div>
								);
							})}
						</div>
						<div className="mt-2 grid grid-cols-3">
							{[
								{
									title: "Taken",
									value: selectedImage.exif.takenAt?.toLocaleDateString(),
								},
								{
									title: "Lens",
									value: selectedImage.exif.LensModel,
								},
								{
									title: "Camera",
									value: selectedImage.camera,
								},
							].map((setting) => {
								return (
									<div key={setting.title} className="w-full border">
										<span className="px-2 w-20 inline-block">
											{setting.title}
										</span>
										<span className="px-2">{setting.value}</span>
									</div>
								);
							})}
						</div>
						<div className="mt-2 grid grid-cols-2">
							{[
								{
									title: "Height",
									value: selectedImage.height.toString(),
								},
								{
									title: "Width",
									value: selectedImage.width.toString(),
								},
							].map((setting) => {
								return (
									<div key={setting.title} className="w-full border">
										<span className="px-2 w-20 inline-block">
											{setting.title}
										</span>
										<span className="px-2">{setting.value}</span>
									</div>
								);
							})}
						</div>
						<div className="mt-2 px-2 pb-2 border">
							<span>Description</span>

							<Controller
								control={control}
								name="description"
								render={({ field: { onChange } }) => (
									<Tiptap onChange={onChange} />
								)}
							/>
						</div>
						<button className="button" type="submit">
							Submit
						</button>
					</form>
				) : null}
			</div>
		</div>
	);
}
