"use client"

import { useState } from "react"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { useUserProfile } from "@/lib/queries/use-user-profile"
import { notify } from "@/lib/notify"

interface ApiKey {
  keyIdentifier: string
  keyPrefix: string
  label: string | null
  createdAt: string
  lastUsedAt: string | null
}

interface WebhookConfiguration {
  webhookUrl: string | null
  webhookSecret: string | null
  webhookEnabled: boolean
  consecutiveFailures: number
}

function useApiKeys() {
  return useQuery({
    queryKey: ["apiKeys"],
    queryFn: async () => {
      const response = await fetch("/api/v1/keys")
      if (!response.ok) throw new Error("failed to load api keys")
      const data = await response.json()
      return data.keys as ApiKey[]
    },
  })
}

function useCreateApiKey() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: async (label: string | null) => {
      const response = await fetch("/api/v1/keys", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ label }),
      })
      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to create api key")
      }
      return response.json() as Promise<{
        fullKey: string
        keyPrefix: string
        keyIdentifier: string
      }>
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["apiKeys"] })
    },
  })
}

function useRevokeApiKey() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: async (keyIdentifier: string) => {
      const response = await fetch(`/api/v1/keys/${keyIdentifier}`, {
        method: "DELETE",
      })
      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to revoke api key")
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["apiKeys"] })
    },
  })
}

function useWebhookConfig() {
  return useQuery({
    queryKey: ["webhookConfig"],
    queryFn: async () => {
      const response = await fetch("/api/webhook-config")
      if (!response.ok) throw new Error("failed to load webhook config")
      return response.json() as Promise<WebhookConfiguration>
    },
  })
}

function useUpdateWebhookConfig() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: async (
      updates: Partial<{
        webhookUrl: string
        webhookSecret: string
        webhookEnabled: boolean
      }>
    ) => {
      const response = await fetch("/api/webhook-config", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(updates),
      })
      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to update webhook config")
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["webhookConfig"] })
    },
  })
}

function useTestWebhook() {
  return useMutation({
    mutationFn: async () => {
      const response = await fetch("/api/webhook-config/test", {
        method: "POST",
      })
      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to send test webhook")
      }
      return response.json() as Promise<{
        delivered: boolean
        statusCode?: number
        error?: string
      }>
    },
  })
}

function ApiKeysSection() {
  const { data: apiKeys, isLoading } = useApiKeys()
  const createApiKey = useCreateApiKey()
  const revokeApiKey = useRevokeApiKey()
  const [newKeyLabel, setNewKeyLabel] = useState("")
  const [revealedKey, setRevealedKey] = useState<string | null>(null)
  const [confirmRevokeIdentifier, setConfirmRevokeIdentifier] = useState<
    string | null
  >(null)

  function handleCreateKey() {
    createApiKey.mutate(newKeyLabel.trim() || null, {
      onSuccess: (data) => {
        setRevealedKey(data.fullKey)
        setNewKeyLabel("")
        notify("api key created")
      },
      onError: (error: Error) => {
        notify(error.message)
      },
    })
  }

  function handleCopyKey() {
    if (revealedKey) {
      navigator.clipboard.writeText(revealedKey)
      notify("api key copied to clipboard")
    }
  }

  function handleRevokeKey(keyIdentifier: string) {
    revokeApiKey.mutate(keyIdentifier, {
      onSuccess: () => {
        notify("api key revoked")
        setConfirmRevokeIdentifier(null)
      },
      onError: (error: Error) => {
        notify(error.message)
      },
    })
  }

  return (
    <div className="mb-6">
      <h3 className="mb-2 text-text-primary">api keys</h3>
      <p className="mb-3 text-text-dim">
        use api keys to authenticate requests to the rest api
      </p>

      {revealedKey && (
        <div className="mb-4 border border-status-warning p-3">
          <p className="mb-2 text-text-secondary">
            copy this key now — it will not be shown again
          </p>
          <div className="flex items-center gap-2">
            <code className="min-w-0 flex-1 overflow-x-auto bg-background-tertiary px-2 py-1 text-text-primary">
              {revealedKey}
            </code>
            <button
              onClick={handleCopyKey}
              className="shrink-0 border border-border px-3 py-1 text-text-secondary transition-colors hover:text-text-primary"
            >
              copy
            </button>
          </div>
          <button
            onClick={() => setRevealedKey(null)}
            className="mt-2 text-text-dim transition-colors hover:text-text-secondary"
          >
            dismiss
          </button>
        </div>
      )}

      {isLoading ? (
        <p className="text-text-dim">loading keys ...</p>
      ) : (
        <>
          {apiKeys && apiKeys.length > 0 && (
            <div className="mb-4 border border-border">
              {apiKeys.map((apiKey) => (
                <div
                  key={apiKey.keyIdentifier}
                  className="flex items-center justify-between border-b border-border px-3 py-2 last:border-b-0"
                >
                  <div className="min-w-0 flex-1">
                    <div className="flex items-center gap-2">
                      <code className="text-text-primary">
                        {apiKey.keyPrefix}...
                      </code>
                      {apiKey.label && (
                        <span className="text-text-dim">{apiKey.label}</span>
                      )}
                    </div>
                    <div className="text-text-dim">
                      created{" "}
                      {new Date(apiKey.createdAt).toLocaleDateString()}
                      {apiKey.lastUsedAt &&
                        ` · last used ${new Date(apiKey.lastUsedAt).toLocaleDateString()}`}
                    </div>
                  </div>
                  {confirmRevokeIdentifier === apiKey.keyIdentifier ? (
                    <div className="flex items-center gap-1">
                      <span className="text-text-dim">revoke?</span>
                      <button
                        onClick={() =>
                          handleRevokeKey(apiKey.keyIdentifier)
                        }
                        className="px-2 py-1 text-status-error transition-colors hover:text-text-primary"
                      >
                        yes
                      </button>
                      <button
                        onClick={() => setConfirmRevokeIdentifier(null)}
                        className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary"
                      >
                        no
                      </button>
                    </div>
                  ) : (
                    <button
                      onClick={() =>
                        setConfirmRevokeIdentifier(apiKey.keyIdentifier)
                      }
                      className="px-2 py-1 text-text-secondary transition-colors hover:text-status-error"
                    >
                      revoke
                    </button>
                  )}
                </div>
              ))}
            </div>
          )}

          {(!apiKeys || apiKeys.length < 5) && (
            <div className="flex items-center gap-2">
              <input
                type="text"
                value={newKeyLabel}
                onChange={(event) => setNewKeyLabel(event.target.value)}
                placeholder="key label (optional)"
                className="min-w-0 flex-1 border border-border bg-background-primary px-3 py-1.5 text-text-primary outline-none placeholder:text-text-dim focus:border-text-dim"
                onKeyDown={(event) => {
                  if (event.key === "Enter") handleCreateKey()
                }}
              />
              <button
                onClick={handleCreateKey}
                disabled={createApiKey.isPending}
                className="shrink-0 border border-border bg-background-tertiary px-4 py-1.5 text-text-primary transition-colors hover:bg-border disabled:opacity-50"
              >
                {createApiKey.isPending ? "creating ..." : "create key"}
              </button>
            </div>
          )}
        </>
      )}
    </div>
  )
}

function WebhookSectionLoading() {
  const { data: webhookConfig, isLoading } = useWebhookConfig()

  if (isLoading) {
    return <p className="text-text-dim">loading webhook configuration ...</p>
  }

  if (!webhookConfig) {
    return <p className="text-text-dim">failed to load webhook configuration</p>
  }

  return <WebhookSection initialConfiguration={webhookConfig} />
}

function WebhookSection({
  initialConfiguration,
}: {
  initialConfiguration: WebhookConfiguration
}) {
  const { data: webhookConfig } = useWebhookConfig()
  const updateWebhookConfig = useUpdateWebhookConfig()
  const testWebhook = useTestWebhook()
  const [webhookUrl, setWebhookUrl] = useState(
    initialConfiguration.webhookUrl ?? ""
  )
  const [webhookSecret, setWebhookSecret] = useState(
    initialConfiguration.webhookSecret ?? ""
  )
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)

  function handleSaveWebhookConfig() {
    updateWebhookConfig.mutate(
      {
        webhookUrl: webhookUrl.trim(),
        webhookSecret: webhookSecret.trim(),
      },
      {
        onSuccess: () => {
          notify("webhook configuration saved")
          setHasUnsavedChanges(false)
        },
        onError: (error: Error) => {
          notify(error.message)
        },
      }
    )
  }

  function handleToggleEnabled() {
    if (!webhookConfig) return

    updateWebhookConfig.mutate(
      { webhookEnabled: !webhookConfig.webhookEnabled },
      {
        onSuccess: () => {
          notify(
            webhookConfig.webhookEnabled
              ? "webhooks disabled"
              : "webhooks enabled"
          )
        },
        onError: (error: Error) => {
          notify(error.message)
        },
      }
    )
  }

  function handleTestWebhook() {
    testWebhook.mutate(undefined, {
      onSuccess: (data) => {
        if (data.delivered) {
          notify(`test webhook delivered (status ${data.statusCode})`)
        } else {
          notify(`test webhook failed: ${data.error}`)
        }
      },
      onError: (error: Error) => {
        notify(error.message)
      },
    })
  }

  function handleGenerateSecret() {
    const array = new Uint8Array(32)
    crypto.getRandomValues(array)
    const generatedSecret = Array.from(array)
      .map((byte) => byte.toString(16).padStart(2, "0"))
      .join("")
    setWebhookSecret(generatedSecret)
    setHasUnsavedChanges(true)
  }

  return (
    <div className="mb-6">
      <h3 className="mb-2 text-text-primary">webhooks</h3>
      <p className="mb-3 text-text-dim">
        receive http post notifications when new entries arrive in your
        subscribed feeds
      </p>

      <div className="mb-4">
        <label className="mb-1 block text-text-secondary">webhook url</label>
        <input
          type="url"
          value={webhookUrl}
          onChange={(event) => {
            setWebhookUrl(event.target.value)
            setHasUnsavedChanges(true)
          }}
          placeholder="https://example.com/webhook"
          className="w-full border border-border bg-background-primary px-3 py-1.5 text-text-primary outline-none placeholder:text-text-dim focus:border-text-dim"
        />
      </div>

      <div className="mb-4">
        <label className="mb-1 block text-text-secondary">
          signing secret
        </label>
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={webhookSecret}
            onChange={(event) => {
              setWebhookSecret(event.target.value)
              setHasUnsavedChanges(true)
            }}
            placeholder="optional hmac-sha256 signing secret"
            className="min-w-0 flex-1 border border-border bg-background-primary px-3 py-1.5 text-text-primary outline-none placeholder:text-text-dim focus:border-text-dim"
          />
          <button
            onClick={handleGenerateSecret}
            className="shrink-0 border border-border px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary"
          >
            generate
          </button>
        </div>
      </div>

      <div className="mb-4 flex items-center gap-4">
        <button
          onClick={handleSaveWebhookConfig}
          disabled={!hasUnsavedChanges || updateWebhookConfig.isPending}
          className="border border-border bg-background-tertiary px-4 py-1.5 text-text-primary transition-colors hover:bg-border disabled:opacity-50"
        >
          {updateWebhookConfig.isPending ? "saving ..." : "save"}
        </button>
        <button
          onClick={handleToggleEnabled}
          disabled={updateWebhookConfig.isPending || (!webhookConfig?.webhookEnabled && !webhookConfig?.webhookUrl)}
          className="border border-border px-4 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:opacity-50"
        >
          {webhookConfig?.webhookEnabled ? "disable" : "enable"}
        </button>
        <button
          onClick={handleTestWebhook}
          disabled={
            testWebhook.isPending ||
            !webhookConfig?.webhookEnabled ||
            !webhookConfig?.webhookUrl
          }
          className="border border-border px-4 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:opacity-50"
        >
          {testWebhook.isPending ? "sending ..." : "send test"}
        </button>
      </div>

      {webhookConfig && (
        <div className="flex items-center gap-3 text-text-dim">
          <span>
            status:{" "}
            <span
              className={
                webhookConfig.webhookEnabled
                  ? "text-text-primary"
                  : "text-text-dim"
              }
            >
              {webhookConfig.webhookEnabled ? "enabled" : "disabled"}
            </span>
          </span>
          {webhookConfig.consecutiveFailures > 0 && (
            <span className="text-status-warning">
              {webhookConfig.consecutiveFailures} consecutive failure
              {webhookConfig.consecutiveFailures !== 1 && "s"}
            </span>
          )}
        </div>
      )}
    </div>
  )
}

export function ApiSettings() {
  const { data: userProfile, isLoading } = useUserProfile()

  if (isLoading) {
    return <p className="px-4 py-6 text-text-dim">loading api settings ...</p>
  }

  if (!userProfile) {
    return (
      <p className="px-4 py-6 text-text-dim">failed to load api settings</p>
    )
  }

  if (userProfile.tier !== "developer") {
    return (
      <div className="px-4 py-3">
        <h3 className="mb-2 text-text-primary">developer api</h3>
        <p className="mb-3 text-text-dim">
          the developer plan includes a read-only rest api and webhook push
          notifications. upgrade to developer to access these features.
        </p>
      </div>
    )
  }

  return (
    <div className="px-4 py-3">
      <ApiKeysSection />
      <WebhookSectionLoading />

      <div>
        <h3 className="mb-2 text-text-primary">api documentation</h3>
        <p className="mb-3 text-text-dim">
          authenticate requests with an api key in the authorization header:
        </p>
        <code className="block bg-background-tertiary px-3 py-2 text-text-secondary">
          Authorization: Bearer asa_your_key_here
        </code>
        <div className="mt-3 space-y-1 text-text-dim">
          <p>get /api/v1/profile — your account info and limits</p>
          <p>get /api/v1/feeds — your subscribed feeds</p>
          <p>get /api/v1/folders — your folders</p>
          <p>
            get /api/v1/entries — entries with ?cursor, ?limit, ?feedIdentifier,
            ?readStatus, ?savedStatus filters
          </p>
          <p>get /api/v1/entries/:id — single entry with full content</p>
        </div>
      </div>
    </div>
  )
}
