import { ArrowLeftIcon, ArrowRightIcon, CheckCircleIcon } from "lucide-react"
import { useState } from "react"
import {
    entropyToMiniSecret,
    generateMnemonic,
    mnemonicToEntropy,
} from "@polkadot-labs/hdkd-helpers"
import { networks } from "@/constants"
import { SubmitHandler, useForm } from "react-hook-form"
import { toHex } from "@polkadot-api/utils"
import { useNavigate } from "react-router-dom"
import { rpc } from "../../api"
import { sr25519CreateDerive } from "@polkadot-labs/hdkd"
import { bytesToHex } from "@noble/ciphers/utils"
import { z } from "zod"
import { Layout2 } from "@/components/Layout2"
import {
    Card,
    CardContent,
    CardDescription,
    CardFooter,
    CardHeader,
    CardTitle,
} from "@/components/ui/card"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import {
    Form,
    FormControl,
    FormDescription,
    FormField,
    FormItem,
    FormLabel,
    FormMessage,
} from "@/components/ui/form"
import {
    RadioGroup,
    RadioGroupItem,
} from "@/components/ui/radio-group"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { Separator } from "@/components/ui/separator"
import { Input } from "@/components/ui/input"
import { Header, BottomNavBar } from "../../components"
import { zodResolver } from "@hookform/resolvers/zod"
import { ScrollArea } from "@/components/ui/scroll-area"
import { cn } from "@/lib/utils"

const schema = z.object({
    cryptoKeyName: z
        .string({ required_error: "This field is required." })
        .min(1, "This field cannot be empty.")
        .refine(
            async (name) => {
                const existingKeys = (await rpc.client.getCryptoKeys()).map(
                    (key) => key.name,
                )
                return !existingKeys.includes(name)
            },
            {
                message: "Name already exists",
            },
        ),
    scheme: z.enum(["Sr25519", "Ed25519", "Ecdsa"]),
    seedPhraseConfirmed: z.boolean().refine((value) => value, {
        message: "Please confirm that you have written down the mnemonic.",
    }),
})

export const AddAccount = () => {
    const navigate = useNavigate()
    const [mnemonic, _] = useState(generateMnemonic(256).split(" "))

    const form = useForm<z.infer<typeof schema>>({
        resolver: zodResolver(schema),
        defaultValues: {
            cryptoKeyName: "",
            scheme: "Sr25519",
            seedPhraseConfirmed: false,
        },
    })
    const {
        handleSubmit,
        control,
        trigger,
        formState: { isSubmitting },
    } = form

    const onSubmit: SubmitHandler<z.infer<typeof schema>> = async (data) => {
        try {
            const entropy = mnemonicToEntropy(mnemonic.join(" "))
            const miniSecret = entropyToMiniSecret(entropy)
            const derive = sr25519CreateDerive(miniSecret)

            const derivationPaths = networks.map((network) => {
                const path = `//${network.value}/0`
                return {
                    chainId: network.chainId,
                    path,
                    publicKey: toHex(derive(`//${network.value}/0`).publicKey),
                }
            })

            await rpc.client.insertCryptoKey({
                type: "Keyset",
                name: data.cryptoKeyName,
                scheme: data.scheme,
                createdAt: Date.now(),
                miniSecret: bytesToHex(miniSecret),
                derivationPaths,
            })

            window.localStorage.setItem("selectedCryptoKeyName", data.cryptoKeyName)
        } finally {
            navigate("/accounts")
        }
    }

    const [step, setStep] = useState(1)
    const handleNext = async () => {
        switch (step) {
            case 1:
                if (!(await trigger("cryptoKeyName"))) return
                break
            case 2:
                if (!(await trigger("scheme"))) return
                break
            default:
                break
        }
        setStep((prevStep) => Math.min(prevStep + 1, 3))
    }

    const handleBack = () => {
        setStep((prevStep) => Math.max(prevStep - 1, 1))
    }

    return (
        <Layout2 innerClassName="bg-muted">
            <Header />
            <ScrollArea className="grow">
                <Form {...form}>
                    <form className="relative grow" onSubmit={handleSubmit(onSubmit)}>
                        <Card className="border-none bg-muted h-full flex flex-col flex-grow w-full max-w-md shadow-none">
                            <CardHeader className="space-y-0 pt-4">
                                <CardTitle className="text-xl font-semibold tracking-normal">
                                    {step === 1
                                        ? "Choose Name"
                                        : step === 2
                                            ? "Select Crypto Scheme"
                                            : "Review Seed Phrase"}
                                </CardTitle>
                                <CardDescription className="text-accent">
                                    Step {step} of 3
                                </CardDescription>
                            </CardHeader>
                            <CardContent>
                                {step === 1 && (
                                    <div className="step-1">
                                        <FormField
                                            name="cryptoKeyName"
                                            control={control}
                                            render={({ field }) => (
                                                <FormItem>
                                                    <FormDescription className="mb-4 text-primary text-xs">
                                                        Set a name for your crypto key. This name will be
                                                        used to identify your crypto key within the
                                                        extension.
                                                    </FormDescription>
                                                    <FormControl>
                                                        <Input
                                                            {...field}
                                                            id="cryptoKeyName"
                                                            type="text"
                                                            placeholder="Set the key name"
                                                        />
                                                    </FormControl>
                                                    <FormMessage />
                                                </FormItem>
                                            )}
                                        />
                                    </div>
                                )}
                                {step === 2 && (
                                    <div className="step-2">
                                        <FormField
                                            name="scheme"
                                            control={control}
                                            render={({ field }) => (
                                                <FormItem>
                                                    <FormDescription className="mb-4 text-primary text-xs">
                                                        Choose the cryptographic signature scheme that meets your
                                                        requirements (default: Sr25519)
                                                    </FormDescription>
                                                    <FormItem className="flex flex-row items-start space-x-3 space-y-0">
                                                        <FormControl>
                                                            <RadioGroup
                                                                onValueChange={(scheme) => field.onChange(scheme)}
                                                                value={field.value}
                                                            >
                                                                <RadioGroupItem value="Sr25519" id="Sr25519" label="Sr25519" />
                                                                <RadioGroupItem value="Ed25519" id="Ed25519" label="Ed25519" />
                                                                <RadioGroupItem value="Ecdsa" id="ECDSA" label="ECDSA" />
                                                            </RadioGroup>
                                                        </FormControl>
                                                    </FormItem>
                                                    <FormMessage />
                                                </FormItem>
                                            )}
                                        />
                                    </div>
                                )}
                                {step === 3 && (
                                    <div className="step-3">
                                        <FormField
                                            name="seedPhraseConfirmed"
                                            control={control}
                                            render={({ field }) => (
                                                <FormItem className="space-y-0 red">
                                                    <FormDescription className="mb-4 text-primary text-xs">
                                                        Your seed phrase is a unique set of words that you
                                                        need to back up and recover your wallet. Do not
                                                        share this with anyone.
                                                    </FormDescription>
                                                    <Textarea
                                                        readOnly
                                                        disabled={isSubmitting}
                                                        aria-label="Created mnemonic phrase"
                                                        id="text"
                                                        rows={4}
                                                        className={cn(
                                                            "min-h-auto h-auto text-justify resize-none cursor-pointer",
                                                            "blur-[2px] hover:blur-none"
                                                        )}
                                                        placeholder={mnemonic.join(" ")}
                                                    />
                                                    <div className="flex pt-4 pb-2">
                                                        <FormControl className="mr-2">
                                                            <Checkbox
                                                                aria-label="I have written down my seed phrase."
                                                                checked={field.value}
                                                                onCheckedChange={field.onChange}
                                                            />
                                                        </FormControl>
                                                        <Label className="block text-primary">
                                                            I have written down my seed phrase.
                                                        </Label>
                                                    </div>
                                                    <FormMessage className="text-xs" />
                                                </FormItem>
                                            )}
                                        />
                                    </div>
                                )}
                            </CardContent>
                            <CardFooter className="flex justify-between mt-6">
                                {step > 1 && (
                                    <Button
                                        disabled={isSubmitting}
                                        onClick={handleBack}
                                        className="flex items-center space-x-2"
                                        variant="secondary"
                                    >
                                        <ArrowLeftIcon className="w-4 h-4" />
                                        <span>Back</span>
                                    </Button>
                                )}
                                {step < 3 ? (
                                    <Button
                                        disabled={isSubmitting}
                                        onClick={handleNext}
                                        className="flex items-center ml-auto space-x-2"
                                        variant="secondary"
                                    >
                                        <span>Next</span>
                                        <ArrowRightIcon className="w-4 h-4" />
                                    </Button>
                                ) : (
                                    <Button
                                        type="submit"
                                        disabled={isSubmitting}
                                        className="flex items-center ml-auto space-x-2"
                                        variant="secondary"
                                    >
                                        <CheckCircleIcon className="w-4 h-4" />
                                        <span>Finish</span>
                                    </Button>
                                )}
                            </CardFooter>
                        </Card>
                    </form>
                </Form>
            </ScrollArea>
            <BottomNavBar currentItem="add" />
        </Layout2>
    )
}
