"use client"

import { useState, type ChangeEvent, type FormEvent } from "react"
import { ReloadIcon } from "@radix-ui/react-icons"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import type { NostrEvent } from "nostr-tools"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { signEvent } from "@/lib/utils"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Copy, Check, ExternalLink, FileImage, Clock, Database, ArrowLeft } from "lucide-react"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { Spinner } from "./spinner"
import { createHash } from "crypto"

interface UploadResponse {
  url: string
  size: number
  type: string
  sha256: string
  uploaded: number
  nip94: {
    tags: string[][]
    content: string
  }
}

function formatBytes(bytes: number, decimals = 2) {
  if (bytes === 0) return "0 Bytes"

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"]

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]
}

function formatDate(timestamp: number) {
  return new Date(timestamp * 1000).toLocaleString()
}

const CopyButton = ({ text }: { text: string }) => {
  const [copied, setCopied] = useState(false)

  const handleCopy = () => {
    navigator.clipboard.writeText(text)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }

  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <Button variant="ghost" size="icon" className="h-6 w-6" onClick={handleCopy}>
            {copied ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
          </Button>
        </TooltipTrigger>
        <TooltipContent>
          <p>{copied ? "Copied!" : "Copy to clipboard"}</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  )
}

const UploadResponseView = ({ data, onReset }: { data: UploadResponse; onReset: () => void }) => {
  const dimensions = data.nip94.tags.find((tag) => tag[0] === "dim")?.[1] || ""
  const blurhash = data.nip94.tags.find((tag) => tag[0] === "blurhash")?.[1] || ""
  const thumbUrl = data.nip94.tags.find((tag) => tag[0] === "thumb")?.[1] || ""

  return (
    <div className="space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-300">
      <div className="flex items-center">
        <Button variant="ghost" size="sm" onClick={onReset} className="gap-1">
          <ArrowLeft className="h-4 w-4" />
          Upload Another
        </Button>
      </div>

      <Card className="w-full">
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle>Upload Successful</CardTitle>
            <Badge variant="outline" className="bg-green-50 text-green-700 border-green-200">
              {data.type}
            </Badge>
          </div>
          <CardDescription>File uploaded on {formatDate(data.uploaded)}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-6">
          <div className="flex flex-col md:flex-row gap-6">
            <div className="flex-1">
              <img
                src={data.url || "/placeholder.svg"}
                alt="Uploaded image"
                className="rounded-md w-full h-auto object-cover max-h-64"
              />
            </div>
            <div className="flex-1 space-y-4">
              <div className="space-y-2">
                <div className="flex items-center text-sm text-muted-foreground">
                  <FileImage className="mr-2 h-4 w-4" />
                  File Size
                </div>
                <div className="font-medium">{formatBytes(data.size)}</div>
              </div>

              <div className="space-y-2">
                <div className="flex items-center text-sm text-muted-foreground">
                  <Clock className="mr-2 h-4 w-4" />
                  Upload Time
                </div>
                <div className="font-medium">{formatDate(data.uploaded)}</div>
              </div>

              {dimensions && (
                <div className="space-y-2">
                  <div className="flex items-center text-sm text-muted-foreground">
                    <Database className="mr-2 h-4 w-4" />
                    Dimensions
                  </div>
                  <div className="font-medium">{dimensions}</div>
                </div>
              )}
            </div>
          </div>

          <Tabs defaultValue="url" className="w-full">
            <TabsList className="grid grid-cols-3">
              <TabsTrigger value="url">URL</TabsTrigger>
              <TabsTrigger value="hash">Hash</TabsTrigger>
              <TabsTrigger value="metadata">Metadata</TabsTrigger>
            </TabsList>

            <TabsContent value="url" className="space-y-4">
              <div className="mt-2 space-y-2">
                <Label>Image URL</Label>
                <div className="flex items-center">
                  <code className="bg-muted p-2 rounded text-xs flex-1 overflow-x-auto">{data.url}</code>
                  <div className="flex ml-2">
                    <CopyButton text={data.url} />
                    <Button variant="ghost" size="icon" className="h-6 w-6" asChild>
                      <a href={data.url} target="_blank" rel="noopener noreferrer">
                        <ExternalLink className="h-3 w-3" />
                      </a>
                    </Button>
                  </div>
                </div>
              </div>

              {thumbUrl && (
                <div className="mt-2 space-y-2">
                  <Label>Thumbnail URL</Label>
                  <div className="flex items-center">
                    <code className="bg-muted p-2 rounded text-xs flex-1 overflow-x-auto">{thumbUrl}</code>
                    <div className="flex ml-2">
                      <CopyButton text={thumbUrl} />
                      <Button variant="ghost" size="icon" className="h-6 w-6" asChild>
                        <a href={thumbUrl} target="_blank" rel="noopener noreferrer">
                          <ExternalLink className="h-3 w-3" />
                        </a>
                      </Button>
                    </div>
                  </div>
                </div>
              )}
            </TabsContent>

            <TabsContent value="hash" className="space-y-4">
              <div className="mt-2 space-y-2">
                <Label>SHA256</Label>
                <div className="flex items-center">
                  <code className="bg-muted p-2 rounded text-xs flex-1 overflow-x-auto">{data.sha256}</code>
                  <CopyButton text={data.sha256} />
                </div>
              </div>

              {blurhash && (
                <div className="mt-2 space-y-2">
                  <Label>Blurhash</Label>
                  <div className="flex items-center">
                    <code className="bg-muted p-2 rounded text-xs flex-1 overflow-x-auto">{blurhash}</code>
                    <CopyButton text={blurhash} />
                  </div>
                </div>
              )}
            </TabsContent>

            <TabsContent value="metadata" className="space-y-4">
              <div className="mt-2">
                <Label className="mb-2 block">NIP94 Tags</Label>
                <div className="grid gap-2">
                  {data.nip94.tags.map((tag, index) => (
                    <div key={index} className="flex items-center bg-muted/50 p-2 rounded">
                      <Badge variant="outline" className="mr-2">
                        {tag[0]}
                      </Badge>
                      <code className="text-xs flex-1 overflow-x-auto">{tag[1]}</code>
                      <CopyButton text={tag[1]} />
                    </div>
                  ))}
                </div>
              </div>
            </TabsContent>
          </Tabs>

          <div className="flex justify-end">
            <Button variant="outline" className="mr-2" asChild>
              <a href={data.url} target="_blank" rel="noopener noreferrer">
                Open Image
              </a>
            </Button>
            <Button
              onClick={() => {
                const markdown = `![Image](${data.url})`
                navigator.clipboard.writeText(markdown)
                alert("Markdown copied to clipboard!")
              }}
            >
              Copy Markdown
            </Button>
          </div>
        </CardContent>
      </Card>
    </div>
  )
}

const UploadComponent = () => {
  const loginType = typeof window !== "undefined" ? window.localStorage.getItem("loginType") : null
  const [previewUrl, setPreviewUrl] = useState("")
  const [isLoading, setIsLoading] = useState(false)
  const [serverChoice, setServerChoice] = useState("blossom.band")
  const [uploadResponse, setUploadResponse] = useState<UploadResponse | null>(null)
  const [showUploadForm, setShowUploadForm] = useState(true)

  const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (file) {
      const url = URL.createObjectURL(file)
      setPreviewUrl(url)

      return () => URL.revokeObjectURL(url)
    }
  }

  const handleServerChange = (value: string) => {
    setServerChoice(value)
  }

  const resetUpload = () => {
    setUploadResponse(null)
    setShowUploadForm(true)
    setPreviewUrl("")
  }

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setIsLoading(true)

    const formData = new FormData(event.currentTarget)
    const file = formData.get("file") as File
    let sha256 = ""
    let finalFileUrl = ""
    console.log("File:", file)

    if (!file.size) {
      alert("Please select a file first")
      setIsLoading(false)
      return
    }

    // If file is present, upload it to the media server
    if (file) {
      const readFileAsArrayBuffer = (file: File): Promise<ArrayBuffer> => {
        return new Promise((resolve, reject) => {
          const reader = new FileReader()
          reader.onload = () => resolve(reader.result as ArrayBuffer)
          reader.onerror = () => reject(reader.error)
          reader.readAsArrayBuffer(file)
        })
      }

      try {
        const arrayBuffer = await readFileAsArrayBuffer(file)
        const hashBuffer = createHash("sha256").update(Buffer.from(arrayBuffer)).digest()
        sha256 = hashBuffer.toString("hex")

        const unixNow = () => Math.floor(Date.now() / 1000)
        const newExpirationValue = () => (unixNow() + 60 * 5).toString()

        const createdAt = Math.floor(Date.now() / 1000)

        // Create auth event for blossom auth via nostr
        const authEvent: NostrEvent = {
          kind: 24242,
          content: "File upload",
          created_at: createdAt,
          tags: [
            ["t", "media"],
            ["x", sha256],
            ["expiration", newExpirationValue()],
          ],
          pubkey: "", // Add a placeholder for pubkey
          id: "", // Add a placeholder for id
          sig: "", // Add a placeholder for sig
        }

        console.log(authEvent)

        // Sign auth event
        const authEventSigned = (await signEvent(loginType, authEvent)) as NostrEvent
        // authEventSigned as base64 encoded string
        const authString = Buffer.from(JSON.stringify(authEventSigned)).toString("base64")

        const blossomServer = "https://" + serverChoice

        await fetch(blossomServer + "/media", {
          method: "PUT",
          body: file,
          headers: { authorization: "Nostr " + authString },
        }).then(async (res) => {
          if (res.ok) {
            const responseText = await res.text()
            const responseJson = JSON.parse(responseText)
            finalFileUrl = responseJson.url
            sha256 = responseJson.sha256

            // Set the upload response data
            setUploadResponse(responseJson)

            if (finalFileUrl) {
              const image = new Image()
              image.src = URL.createObjectURL(file)
              await new Promise((resolve) => {
                image.onload = resolve
              })

            }

            setIsLoading(false)
            if (finalFileUrl != null) {
              setShowUploadForm(false)
            }
          } else {
            throw new Error("Failed to upload file: " + (await res.text()))
          }
        })
      } catch (error) {
        alert(error)
        console.error("Error reading file:", error)
        setIsLoading(false)
      }
    }
  }

  return (
    <div className="w-full mx-auto">
      {showUploadForm ? (
        <Card className="w-full">
          <CardHeader>
            <CardTitle>Upload Image</CardTitle>
            <CardDescription>Select an image to upload to {serverChoice}</CardDescription>
          </CardHeader>
          <CardContent>
            <form className="space-y-4" onSubmit={onSubmit}>
              <div className="grid w-full items-center gap-1.5">
                <Label htmlFor="file">Select File</Label>
                <Input id="file" name="file" type="file" accept="image/*" onChange={handleFileChange} />
              </div>

              <div className="grid grid-cols-2 w-full items-center gap-1.5">
                <Label htmlFor="server-select">Upload to</Label>
                <Select onValueChange={handleServerChange} value={serverChoice}>
                  <SelectTrigger className="w-full" id="server-select">
                    <SelectValue placeholder={serverChoice} />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="blossom.band">blossom.band</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              {previewUrl && (
                <div className="mt-4 rounded-md overflow-hidden">
                  <img
                    src={previewUrl || "/placeholder.svg"}
                    alt="Preview"
                    className="w-full max-h-80 object-contain"
                  />
                </div>
              )}

              {isLoading ? (
                <Button className="w-full" disabled>
                  Uploading... <ReloadIcon className="ml-2 h-4 w-4 animate-spin" />
                </Button>
              ) : (
                <Button className="w-full" type="submit">
                  Upload
                </Button>
              )}
            </form>
          </CardContent>
        </Card>
      ) : uploadResponse ? (
        <UploadResponseView data={uploadResponse} onReset={resetUpload} />
      ) : (
        <Card className="w-full">
          <CardContent className="flex flex-col items-center justify-center p-8">
            <Spinner />
            <p className="mt-4">Processing upload...</p>
          </CardContent>
        </Card>
      )}
    </div>
  )
}

export default UploadComponent
