import { NDKEvent, NDKKind, NDKUserProfile } from '@nostr-dev-kit/ndk';
import { useQueryClient } from '@tanstack/react-query';
import { message } from '@tauri-apps/plugin-dialog';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Link } from 'react-router-dom';

import { useNDK } from '@libs/ndk/provider';
import { useStorage } from '@libs/storage/provider';

import {
  ArrowLeftIcon,
  CheckCircleIcon,
  LoaderIcon,
  PlusIcon,
  UnverifiedIcon,
} from '@shared/icons';

import { useNostr } from '@utils/hooks/useNostr';

export function EditProfileScreen() {
  const queryClient = useQueryClient();

  const [loading, setLoading] = useState(false);
  const [picture, setPicture] = useState('');
  const [banner, setBanner] = useState('');
  const [nip05, setNIP05] = useState({ verified: true, text: '' });

  const { db } = useStorage();
  const { ndk } = useNDK();
  const { upload } = useNostr();
  const {
    register,
    handleSubmit,
    reset,
    setError,
    formState: { isValid, errors },
  } = useForm({
    defaultValues: async () => {
      const res: NDKUserProfile = queryClient.getQueryData(['user', db.account.pubkey]);
      if (res.image) {
        setPicture(res.image);
      }
      if (res.banner) {
        setBanner(res.banner);
      }
      if (res.nip05) {
        setNIP05((prev) => ({ ...prev, text: res.nip05 }));
      }
      return res;
    },
  });

  const uploadAvatar = async () => {
    try {
      setLoading(true);

      const image = await upload();

      if (image) {
        setPicture(image);
        setLoading(false);
      }
    } catch (e) {
      setLoading(false);
      await message(`Upload failed, error: ${e}`, { title: 'Lume', type: 'error' });
    }
  };

  const uploadBanner = async () => {
    try {
      setLoading(true);

      const image = await upload();

      if (image) {
        setBanner(image);
        setLoading(false);
      }
    } catch (e) {
      setLoading(false);
      await message(`Upload failed, error: ${e}`, { title: 'Lume', type: 'error' });
    }
  };

  const onSubmit = async (data: NDKUserProfile) => {
    // start loading
    setLoading(true);

    const content = {
      ...data,
      username: data.name,
      display_name: data.name,
      bio: data.about,
      image: data.picture,
    };

    const event = new NDKEvent(ndk);
    event.kind = NDKKind.Metadata;
    event.tags = [];

    if (data.nip05) {
      const user = ndk.getUser({ pubkey: db.account.pubkey });
      const verify = await user.validateNip05(data.nip05);
      if (verify) {
        event.content = JSON.stringify({ ...content, nip05: data.nip05 });
      } else {
        setNIP05((prev) => ({ ...prev, verified: false }));
        setError('nip05', {
          type: 'manual',
          message: "Can't verify your Lume ID / NIP-05, please check again",
        });
      }
    } else {
      event.content = JSON.stringify(content);
    }

    const publishedRelays = await event.publish();

    if (publishedRelays) {
      // invalid cache
      queryClient.invalidateQueries({
        queryKey: ['user', db.account.pubkey],
      });
      // reset form
      reset();
      // reset state
      setLoading(false);
      setPicture(null);
      setBanner(null);
    } else {
      setLoading(false);
    }
  };

  return (
    <div className="flex h-full w-full flex-col overflow-y-auto">
      <div className="flex h-14 shrink-0 items-center justify-between px-3">
        <Link
          to="/personal"
          className="inline-flex h-10 w-20 items-center justify-center gap-2 font-medium text-neutral-700 dark:text-neutral-300"
        >
          <ArrowLeftIcon className="h-4 w-4" />
          Back
        </Link>
        <h1 className="font-semibold">Edit Profile</h1>
        <div className="w-20" />
      </div>
      <div className="mx-auto w-full max-w-md">
        <form onSubmit={handleSubmit(onSubmit)} className="mb-0">
          <input type={'hidden'} {...register('picture')} value={picture} />
          <input type={'hidden'} {...register('banner')} value={banner} />
          <div className="flex flex-col items-center justify-center">
            <div className="relative h-36 w-full">
              {banner ? (
                <img
                  src={banner}
                  alt="user's banner"
                  className="h-full w-full rounded-xl object-cover"
                />
              ) : (
                <div className="h-full w-full rounded-xl bg-neutral-200 dark:bg-neutral-900" />
              )}
              <div className="absolute left-1/2 top-1/2 z-10 h-full w-full -translate-x-1/2 -translate-y-1/2 transform overflow-hidden rounded-xl">
                <button
                  type="button"
                  onClick={() => uploadBanner()}
                  className="inline-flex h-full w-full items-center justify-center bg-black/20 text-white"
                >
                  <PlusIcon className="h-5 w-5" />
                </button>
              </div>
            </div>
            <div className="mb-5 px-4">
              <div className="relative z-10 -mt-7 h-14 w-14 overflow-hidden rounded-xl ring-2 ring-white dark:ring-black">
                <img
                  src={picture}
                  alt="user's avatar"
                  className="h-14 w-14 rounded-xl object-cover"
                />
                <div className="absolute left-1/2 top-1/2 z-10 h-full w-full -translate-x-1/2 -translate-y-1/2 transform">
                  <button
                    type="button"
                    onClick={() => uploadAvatar()}
                    className="inline-flex h-full w-full items-center justify-center rounded-xl bg-black/50 text-white"
                  >
                    <PlusIcon className="h-5 w-5" />
                  </button>
                </div>
              </div>
            </div>
          </div>
          <div className="flex flex-col gap-4">
            <div className="flex flex-col gap-1">
              <label
                htmlFor="display_name"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                Display Name
              </label>
              <input
                type={'text'}
                {...register('display_name', {
                  required: true,
                  minLength: 4,
                })}
                spellCheck={false}
                className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
              />
            </div>
            <div className="flex flex-col gap-1">
              <label
                htmlFor="name"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                Name
              </label>
              <input
                type={'text'}
                {...register('name', {
                  required: true,
                  minLength: 4,
                })}
                spellCheck={false}
                className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
              />
            </div>
            <div className="flex flex-col gap-1">
              <label
                htmlFor="nip05"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                NIP-05
              </label>
              <div className="relative">
                <input
                  {...register('nip05', {
                    required: true,
                    minLength: 4,
                  })}
                  spellCheck={false}
                  className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
                />
                <div className="absolute right-2 top-1/2 -translate-y-1/2 transform">
                  {nip05.verified ? (
                    <span className="inline-flex h-6 items-center gap-1 rounded-full bg-teal-500 px-1 pr-1.5 text-xs font-medium text-white">
                      <CheckCircleIcon className="h-4 w-4" />
                      Verified
                    </span>
                  ) : (
                    <span className="inline-flex h-6 items-center gap-1 rounded bg-red-500 pl-1 pr-1.5 text-xs font-medium text-white">
                      <UnverifiedIcon className="h-4 w-4" />
                      Unverified
                    </span>
                  )}
                </div>
                {errors.nip05 && (
                  <p className="mt-1 text-sm text-red-400">
                    {errors.nip05.message.toString()}
                  </p>
                )}
              </div>
            </div>
            <div className="flex flex-col gap-1">
              <label
                htmlFor="website"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                Website
              </label>
              <input
                type={'text'}
                {...register('website', { required: false })}
                spellCheck={false}
                className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
              />
            </div>
            <div className="flex flex-col gap-1">
              <label
                htmlFor="website"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                Lightning address
              </label>
              <input
                type={'text'}
                {...register('lud16', { required: false })}
                spellCheck={false}
                className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
              />
            </div>
            <div className="flex flex-col gap-1">
              <label
                htmlFor="about"
                className="text-sm font-semibold uppercase tracking-wider"
              >
                Bio
              </label>
              <textarea
                {...register('about')}
                spellCheck={false}
                className="relative h-20 w-full resize-none rounded-lg bg-neutral-100 px-3 py-2 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100"
              />
            </div>
            <div>
              <button
                type="submit"
                disabled={!isValid}
                className="mx-auto inline-flex h-9 w-full transform items-center justify-center gap-1 rounded-lg bg-blue-500 font-medium text-white hover:bg-blue-600 focus:outline-none active:translate-y-1 disabled:pointer-events-none disabled:opacity-50"
              >
                {loading ? (
                  <LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-white" />
                ) : (
                  'Update'
                )}
              </button>
            </div>
          </div>
        </form>
      </div>
    </div>
  );
}
