"use client";

import type React from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { useContext, useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { authLocalization } from "../../lib/auth-localization";
import { AuthUIContext } from "../../lib/auth-ui-provider";
import { cn } from "../../lib/utils";
import type { Organization } from "../../types/organization";
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Button } from "../ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "../ui/form";
import { Input } from "../ui/input";

// Define the form schema with Zod
const organizationSchema = z.object({
  name: z.string().min(1, "Organization name is required"),
  slug: z
    .string()
    .min(1, "Organization slug is required")
    .regex(
      /^[a-z0-9-]+$/,
      "Slug can only contain lowercase letters, numbers, and hyphens"
    ),
  logo: z.any().optional(),
});

export type OrganizationData = z.infer<typeof organizationSchema>;

export type OrganizationCreatorClassNames = {
  base?: string;
  form?: string;
  formGroup?: string;
  label?: string;
  input?: string;
  fileInput?: string;
  fileInputButton?: string;
  fileInputText?: string;
  footer?: string;
  submitButton?: string;
  avatar?: string;
  avatarFallback?: string;
  logoContainer?: string;
  logoInstructions?: string;
  errorMessage?: string;
};

export interface OrganizationCreatorProps {
  className?: string;
  classNames?: OrganizationCreatorClassNames;
  logoSize?: number;
  logoExtension?: string;
  onSuccess?: () => void;
  organization?: Organization;
  mode?: "create" | "update";
}

// Image processing functions
async function resizeAndCropImage(
  file: File,
  name: string,
  size: number,
  logoExtension: string
): Promise<File> {
  const image = await loadImage(file);

  const canvas = document.createElement("canvas");
  canvas.width = canvas.height = size;

  const ctx = canvas.getContext("2d");

  const minEdge = Math.min(image.width, image.height);

  const sx = (image.width - minEdge) / 2;
  const sy = (image.height - minEdge) / 2;
  const sWidth = minEdge;
  const sHeight = minEdge;

  ctx?.drawImage(image, sx, sy, sWidth, sHeight, 0, 0, size, size);

  const resizedImageBlob = await new Promise<Blob | null>((resolve) =>
    canvas.toBlob(resolve, `image/${logoExtension}`)
  );

  return new File([resizedImageBlob as BlobPart], `${name}.${logoExtension}`, {
    type: `image/${logoExtension}`,
  });
}

const generateSlug = (text: string): string => {
  return text
    .toLowerCase()
    .replace(/\s+/g, "-") // Replace spaces with hyphens
    .replace(/[^\w-]+/g, "") // Remove non-word chars
    .replace(/--+/g, "-") // Replace multiple hyphens with single hyphen
    .replace(/^-+/, "") // Trim hyphens from start
    .replace(/-+$/, ""); // Trim hyphens from end
};

async function loadImage(file: File): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.crossOrigin = "anonymous";
    const reader = new FileReader();

    reader.onload = (e) => {
      image.src = e.target?.result as string;
    };

    image.onload = () => resolve(image);
    image.onerror = (err) => reject(err);

    reader.readAsDataURL(file);
  });
}

async function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result as string);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

async function urlToFile(
  url: string,
  filename: string,
  mimeType: string
): Promise<File> {
  const response = await fetch(url);
  const blob = await response.blob();
  return new File([blob], filename, { type: mimeType });
}

export function OrganizationCreator({
  className,
  classNames,
  logoSize = 128,
  logoExtension = "png",
  onSuccess,
  organization,
  mode = "create",
}: OrganizationCreatorProps) {
  const { uploadAvatar, toast, authClient } = useContext(AuthUIContext);
  const [logo, setLogo] = useState<File | null>(null);
  const [logoPreview, setLogoPreview] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [isLoading, setIsLoading] = useState(false);

  // Set default submit button text based on mode
  const defaultSubmitText = mode === "create" ? "Create" : "Update";
  const actualSubmitButtonText = defaultSubmitText;

  // Initialize React Hook Form with Zod validation
  const form = useForm<OrganizationData>({
    resolver: zodResolver(organizationSchema),
    defaultValues: {
      name: organization?.name || "",
      slug: organization?.slug || "",
    },
  });

  // Load existing organization data when provided
  useEffect(() => {
    if (organization) {
      form.reset({
        name: organization.name,
        slug: organization.slug,
      });
      // Set logo preview if available
      if (organization.logo) {
        setLogoPreview(organization.logo);

        // Optionally convert the logo URL to a File object for later processing
        // if (organization.logo.startsWith("http")) {
        //   const loadLogoFile = async () => {
        //     try {
        //       const file = await urlToFile(
        //         organization.logo as string,
        //         `org-logo-${organization.slug}.${logoExtension}`,
        //         `image/${logoExtension}`
        //       );
        //       setLogo(file);
        //     } catch (err) {
        //       console.error("Error loading logo from URL:", err);
        //     }
        //   };

        //   loadLogoFile();
        // }
      }
    }
  }, [
    organization,
    form,
    // logoExtension
  ]);

  const handleOrganizationSubmit = async (data: OrganizationData) => {
    try {
      if (mode === "create") {
        // Create new organization
        await authClient.organization.create(
          {
            name: data.name,
            slug: data.slug,
            logo: data.logo,
          },
          {
            onSuccess(context) {
              const newOrg = context.data;
              if (newOrg?.id) {
                authClient.organization.setActive({
                  organizationId: newOrg.id,
                });
              }
              resetForm();
              onSuccess?.();
              toast({
                variant: "success",
                message: `Organization "${data.name}" has been created.`,
              });
            },
            onError(context) {
              toast({
                variant: "error",
                message: context?.error?.message,
              });
            },
          }
        );
      } else if (mode === "update" && organization?.id) {
        // Update existing organization
        await authClient.organization.update(
          {
            organizationId: organization.id,
            data: {
              name: data.name,
              logo: data.logo,
            },
          },
          {
            onSuccess() {
              onSuccess?.();
              toast({
                variant: "success",
                message: `Organization "${data.name}" has been updated.`,
              });
            },
            onError(context) {
              toast({
                variant: "error",
                message:
                  context?.error?.message || "Failed to update organization",
              });
            },
          }
        );
      }
    } catch (err) {
      console.error(`Failed to ${mode} organization:`, err);
      toast({
        variant: "error",
        message: `Failed to ${mode} organization. Please try again.`,
      });
    }
  };

  // Handle file selection
  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      const file = e.target.files[0];
      try {
        // Generate a temporary name for the logo based on timestamp
        const tempName = `org-logo-${Date.now()}`;

        // Process the image
        const processedFile = await resizeAndCropImage(
          file,
          tempName,
          logoSize,
          logoExtension
        );

        // Create a preview
        const preview = await fileToBase64(processedFile);

        setLogo(processedFile);
        setLogoPreview(preview);
        form.setValue("logo", processedFile);
      } catch (err) {
        console.error("Error processing logo:", err);
        toast?.({
          variant: "error",
          message: "Failed to process image. Please try another file.",
        });
      }
    }
  };

  const handleNameChange = (value: string) => {
    form.setValue("name", value);

    // Only auto-generate slug if user hasn't manually edited it yet or if it's a new organization
    if (mode === "create" || !organization?.slug) {
      form.setValue("slug", generateSlug(value));
    }
  };

  const isSubmitting = form.formState.isSubmitting || isLoading;

  const handleSubmit = async (data: OrganizationData) => {
    try {
      if (logo) {
        if (uploadAvatar) {
          const logoUrl = await uploadAvatar(logo);
          data.logo = logoUrl;
        } else {
          const base64 = await fileToBase64(logo);
          data.logo = base64;
        }
      } else if (logoPreview && organization?.logo) {
        // Keep existing logo if no new one was uploaded
        data.logo = organization.logo;
      }

      await handleOrganizationSubmit(data);
    } catch (err) {
      console.error(`Failed to ${mode} organization:`, err);
    }
  };

  // Reset form state
  const resetForm = () => {
    form.reset();
    setLogo(null);
    setLogoPreview(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  };

  return (
    <div className={cn("w-full", className, classNames?.base)}>
      <Form {...form}>
        <form
          onSubmit={form.handleSubmit(handleSubmit)}
          className={cn("space-y-4", classNames?.form)}
        >
          <div
            className={cn(
              "flex flex-col items-center mb-4",
              classNames?.logoContainer
            )}
          >
            <button
              type="button"
              onClick={() => fileInputRef.current?.click()}
              className="relative group cursor-pointer"
              disabled={isSubmitting}
            >
              <Avatar className={cn("h-20 w-20", classNames?.avatar)}>
                {logoPreview ? (
                  <AvatarImage
                    src={logoPreview || "/placeholder.svg"}
                    alt="Organization logo preview"
                  />
                ) : (
                  <AvatarFallback className={classNames?.avatarFallback}>
                    {form.getValues("name")
                      ? form.getValues("name").charAt(0).toUpperCase()
                      : "O"}
                  </AvatarFallback>
                )}
              </Avatar>
              <div className="absolute inset-0 bg-black/50 rounded-full opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity">
                <span className="text-white text-xs">Change</span>
              </div>
            </button>
            <input
              ref={fileInputRef}
              id="org-logo"
              type="file"
              accept="image/*"
              onChange={handleFileChange}
              className="hidden"
              disabled={isSubmitting}
            />
            <p
              className={cn(
                "text-xs text-muted-foreground mt-2",
                classNames?.logoInstructions
              )}
            >
              Click to upload a logo
            </p>
          </div>

          <FormField
            control={form.control}
            name="name"
            render={({ field }) => (
              <FormItem className={cn("space-y-2", classNames?.formGroup)}>
                <FormLabel className={classNames?.label}>
                  Organization Name
                </FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    placeholder="Name"
                    className={classNames?.input}
                    disabled={isSubmitting}
                    autoComplete="off"
                    onChange={(e) => handleNameChange(e.target.value)}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="slug"
            render={({ field }) => (
              <FormItem className={cn("space-y-2", classNames?.formGroup)}>
                <FormLabel className={classNames?.label}>
                  Organization Slug
                </FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    placeholder="Slug"
                    className={classNames?.input}
                    disabled={
                      isSubmitting ||
                      (mode === "update" && !!organization?.slug)
                    }
                    autoComplete="off"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <div
            className={cn("flex justify-end gap-4 pt-4", classNames?.footer)}
          >
            {onSuccess && (
              <Button
                type="button"
                disabled={isSubmitting}
                className={"w-24"}
                variant={"outline"}
                onClick={onSuccess}
              >
                Cancel
              </Button>
            )}
            <Button
              type="submit"
              disabled={isSubmitting}
              className={cn("w-24", classNames?.submitButton)}
            >
              {isSubmitting
                ? mode === "create"
                  ? "Creating..."
                  : "Updating..."
                : actualSubmitButtonText}
            </Button>
          </div>
        </form>
      </Form>
    </div>
  );
}
