"use client";

import { FC, useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
// icons
import { Info, Lock } from "lucide-react";
import { IProject, IWorkspace } from "@plane/types";
// ui
import {
  Button,
  CustomSelect,
  Input,
  TextArea,
  TOAST_TYPE,
  setToast,
  CustomEmojiIconPicker,
  EmojiIconPickerTypes,
  Tooltip,
} from "@plane/ui";
// components
import { Logo } from "@/components/common";
import { ImagePickerPopover } from "@/components/core";
// constants
import { PROJECT_UPDATED } from "@/constants/event-tracker";
import { NETWORK_CHOICES } from "@/constants/project";
// helpers
import { renderFormattedDate } from "@/helpers/date-time.helper";
// hooks
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
import { useEventTracker, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// services
import { ProjectService } from "@/services/project";
// types
export interface IProjectDetailsForm {
  project: IProject;
  workspaceSlug: string;
  projectId: string;
  isAdmin: boolean;
}
const projectService = new ProjectService();
export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
  const { project, workspaceSlug, projectId, isAdmin } = props;
  // states
  const [isOpen, setIsOpen] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  // store hooks
  const { captureProjectEvent } = useEventTracker();
  const { updateProject } = useProject();
  const { isMobile } = usePlatformOS();
  // form info
  const {
    handleSubmit,
    watch,
    control,
    setValue,
    setError,
    reset,
    formState: { errors, dirtyFields },
    getValues,
  } = useForm<IProject>({
    defaultValues: {
      ...project,
      workspace: (project.workspace as IWorkspace).id,
    },
  });

  useEffect(() => {
    if (project && projectId !== getValues("id")) {
      reset({
        ...project,
        workspace: (project.workspace as IWorkspace).id,
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [project, projectId]);
  const handleIdentifierChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = event.target;
    const alphanumericValue = value.replace(/[^a-zA-Z0-9]/g, "");
    const formattedValue = alphanumericValue.toUpperCase();
    setValue("identifier", formattedValue);
  };
  const handleUpdateChange = async (payload: Partial<IProject>) => {
    if (!workspaceSlug || !project) return;
    return updateProject(workspaceSlug.toString(), project.id, payload)
      .then((res) => {
        const changed_properties = Object.keys(dirtyFields);

        captureProjectEvent({
          eventName: PROJECT_UPDATED,
          payload: {
            ...res,
            changed_properties: changed_properties,
            state: "SUCCESS",
            element: "Project general settings",
          },
        });
        setToast({
          type: TOAST_TYPE.SUCCESS,
          title: "Success!",
          message: "Project updated successfully",
        });
      })
      .catch((error) => {
        captureProjectEvent({
          eventName: PROJECT_UPDATED,
          payload: { ...payload, state: "FAILED", element: "Project general settings" },
        });
        setToast({
          type: TOAST_TYPE.ERROR,
          title: "Error!",
          message: error?.error ?? "Project could not be updated. Please try again.",
        });
      });
  };
  const onSubmit = async (formData: IProject) => {
    if (!workspaceSlug) return;
    setIsLoading(true);
    const payload: Partial<IProject> = {
      name: formData.name,
      network: formData.network,
      identifier: formData.identifier,
      description: formData.description,
      cover_image: formData.cover_image,
      logo_props: formData.logo_props,
    };

    if (project.identifier !== formData.identifier)
      await projectService
        .checkProjectIdentifierAvailability(workspaceSlug as string, payload.identifier ?? "")
        .then(async (res) => {
          if (res.exists) setError("identifier", { message: "Identifier already exists" });
          else await handleUpdateChange(payload);
        });
    else await handleUpdateChange(payload);
    setTimeout(() => {
      setIsLoading(false);
    }, 300);
  };
  const currentNetwork = NETWORK_CHOICES.find((n) => n.key === project?.network);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="relative mt-6 h-44 w-full">
        <div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" />
        <img src={watch("cover_image")!} alt={watch("cover_image")!} className="h-44 w-full rounded-md object-cover" />
        <div className="z-5 absolute bottom-4 flex w-full items-end justify-between gap-3 px-4">
          <div className="flex flex-grow gap-3 truncate">
            <Controller
              control={control}
              name="logo_props"
              render={({ field: { value, onChange } }) => (
                <CustomEmojiIconPicker
                  isOpen={isOpen}
                  handleToggle={(val: boolean) => setIsOpen(val)}
                  className="flex items-center justify-center"
                  buttonClassName="flex h-[52px] w-[52px] flex-shrink-0 items-center justify-center rounded-lg bg-custom-background-90"
                  label={<Logo logo={value} size={28} />}
                  onChange={(val) => {
                    let logoValue = {};

                    if (val?.type === "emoji")
                      logoValue = {
                        value: convertHexEmojiToDecimal(val.value.unified),
                        url: val.value.imageUrl,
                      };
                    else if (val?.type === "icon") logoValue = val.value;

                    onChange({
                      in_use: val?.type,
                      [val?.type]: logoValue,
                    });
                    setIsOpen(false);
                  }}
                  defaultIconColor={value?.in_use && value.in_use === "icon" ? value?.icon?.color : undefined}
                  defaultOpen={
                    value.in_use && value.in_use === "emoji" ? EmojiIconPickerTypes.EMOJI : EmojiIconPickerTypes.ICON
                  }
                  disabled={!isAdmin}
                />
              )}
            />
            <div className="flex flex-col gap-1 truncate text-white">
              <span className="truncate text-lg font-semibold">{watch("name")}</span>
              <span className="flex items-center gap-2 text-sm">
                <span>{watch("identifier")} .</span>
                <span className="flex items-center gap-1.5">
                  {project.network === 0 && <Lock className="h-2.5 w-2.5 text-white " />}
                  {currentNetwork?.label}
                </span>
              </span>
            </div>
          </div>
          <div className="flex flex-shrink-0 justify-center">
            <div>
              <Controller
                control={control}
                name="cover_image"
                render={({ field: { value, onChange } }) => (
                  <ImagePickerPopover
                    label={"Change cover"}
                    control={control}
                    onChange={onChange}
                    value={value}
                    disabled={!isAdmin}
                  />
                )}
              />
            </div>
          </div>
        </div>
      </div>
      <div className="my-8 flex flex-col gap-8">
        <div className="flex flex-col gap-1">
          <h4 className="text-sm">Project Name</h4>
          <Controller
            control={control}
            name="name"
            rules={{
              required: "Name is required",
              maxLength: {
                value: 255,
                message: "Project name should be less than 255 characters",
              },
            }}
            render={({ field: { value, onChange, ref } }) => (
              <Input
                id="name"
                name="name"
                type="text"
                ref={ref}
                value={value}
                onChange={onChange}
                hasError={Boolean(errors.name)}
                className="rounded-md !p-3 font-medium"
                placeholder="Project Name"
                disabled={!isAdmin}
              />
            )}
          />
          <span className="text-xs text-red-500">{errors?.name?.message}</span>
        </div>
        <div className="flex flex-col gap-1">
          <h4 className="text-sm">Description</h4>
          <Controller
            name="description"
            control={control}
            render={({ field: { value, onChange } }) => (
              <TextArea
                id="description"
                name="description"
                value={value}
                placeholder="Enter project description"
                onChange={onChange}
                className="min-h-[102px] text-sm font-medium"
                hasError={Boolean(errors?.description)}
                disabled={!isAdmin}
              />
            )}
          />
        </div>
        <div className="flex w-full justify-between gap-10">
          <div className="flex w-1/2 flex-col gap-1">
            <h4 className="text-sm">Project ID</h4>
            <div className="relative">
              <Controller
                control={control}
                name="identifier"
                rules={{
                  required: "Project ID is required",
                  validate: (value) =>
                    /^[ÇŞĞIİÖÜA-Z0-9]+$/.test(value.toUpperCase()) ||
                    "Only Alphanumeric & Non-latin characters are allowed.",
                  minLength: {
                    value: 1,
                    message: "Project ID must at least be of 1 character",
                  },
                  maxLength: {
                    value: 5,
                    message: "Project ID must at most be of 5 characters",
                  },
                }}
                render={({ field: { value, ref } }) => (
                  <Input
                    id="identifier"
                    name="identifier"
                    type="text"
                    value={value}
                    onChange={handleIdentifierChange}
                    ref={ref}
                    hasError={Boolean(errors.identifier)}
                    placeholder="Enter Project ID"
                    className="w-full font-medium"
                    disabled={!isAdmin}
                  />
                )}
              />
              <Tooltip
                isMobile={isMobile}
                tooltipContent="Helps you identify issues in the project uniquely, (e.g. APP-123). Max 5 characters."
                className="text-sm"
                position="right-top"
              >
                <Info className="absolute right-2 top-2.5 h-4 w-4 text-custom-text-400" />
              </Tooltip>
            </div>
            <span className="text-xs text-red-500">
              <>{errors?.identifier?.message}</>
            </span>
          </div>
          <div className="flex w-1/2 flex-col gap-1">
            <h4 className="text-sm">Network</h4>
            <Controller
              name="network"
              control={control}
              render={({ field: { value, onChange } }) => {
                const selectedNetwork = NETWORK_CHOICES.find((n) => n.key === value);

                return (
                  <CustomSelect
                    value={value}
                    onChange={onChange}
                    label={
                      <div className="flex items-center gap-1">
                        {selectedNetwork ? (
                          <>
                            <selectedNetwork.icon className="h-3.5 w-3.5" />
                            {selectedNetwork.label}
                          </>
                        ) : (
                          <span className="text-custom-text-400">Select network</span>
                        )}
                      </div>
                    }
                    buttonClassName="!border-custom-border-200 !shadow-none font-medium rounded-md"
                    input
                    disabled={!isAdmin}
                    // optionsClassName="w-full"
                  >
                    {NETWORK_CHOICES.map((network) => (
                      <CustomSelect.Option key={network.key} value={network.key}>
                        <div className="flex items-start gap-2">
                          <network.icon className="h-3.5 w-3.5" />
                          <div className="-mt-1">
                            <p>{network.label}</p>
                            <p className="text-xs text-custom-text-400">{network.description}</p>
                          </div>
                        </div>
                      </CustomSelect.Option>
                    ))}
                  </CustomSelect>
                );
              }}
            />
          </div>
        </div>
        <div className="flex items-center justify-between py-2">
          <>
            <Button variant="primary" type="submit" loading={isLoading} disabled={!isAdmin}>
              {isLoading ? "Updating..." : "Update project"}
            </Button>
            <span className="text-sm italic text-custom-sidebar-text-400">
              Created on {renderFormattedDate(project?.created_at)}
            </span>
          </>
        </div>
      </div>
    </form>
  );
};