"use client"

import { useEffect, useRef, useState } from "react"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { useSearchParams } from "next/navigation"
import { useUserProfile } from "@/lib/queries/use-user-profile"
import { queryKeys } from "@/lib/queries/query-keys"
import { TIER_LIMITS } from "@asa-news/shared"
import { classNames } from "@/lib/utilities"
import { notify } from "@/lib/notify"

function useCreateCheckoutSession() {
  return useMutation({
    mutationFn: async ({
      billingInterval,
      targetTier,
    }: {
      billingInterval: "monthly" | "yearly"
      targetTier: "pro" | "developer"
    }) => {
      const response = await fetch("/api/billing/create-checkout-session", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ billingInterval, targetTier }),
      })

      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to create checkout session")
      }

      const data = await response.json()
      return data as { url?: string; upgraded?: boolean }
    },
  })
}

function useCreatePortalSession() {
  return useMutation({
    mutationFn: async () => {
      const response = await fetch("/api/billing/create-portal-session", {
        method: "POST",
      })

      if (!response.ok) {
        const data = await response.json()
        throw new Error(data.error || "failed to create portal session")
      }

      const data = await response.json()
      return data as { url: string }
    },
  })
}

const PRO_FEATURES = [
  `${TIER_LIMITS.pro.maximumFeeds} feeds`,
  `${TIER_LIMITS.pro.historyRetentionDays}-day history retention`,
  `${TIER_LIMITS.pro.refreshIntervalSeconds / 60}-minute refresh interval`,
  "authenticated feeds",
  "opml export",
  "manual feed refresh",
]

const DEVELOPER_FEATURES = [
  `${TIER_LIMITS.developer.maximumFeeds} feeds`,
  "everything in pro",
  "read-only rest api",
  "webhook push notifications",
]

function UpgradeCard({
  targetTier,
  features,
  monthlyPrice,
  yearlyPrice,
}: {
  targetTier: "pro" | "developer"
  features: string[]
  monthlyPrice: string
  yearlyPrice: string
}) {
  const [billingInterval, setBillingInterval] = useState<
    "monthly" | "yearly"
  >("yearly")
  const queryClient = useQueryClient()
  const createCheckoutSession = useCreateCheckoutSession()

  function handleUpgrade() {
    createCheckoutSession.mutate(
      { billingInterval, targetTier },
      {
        onSuccess: (data) => {
          if (data.upgraded) {
            queryClient.invalidateQueries({
              queryKey: queryKeys.userProfile.all,
            })
            notify(`upgraded to ${targetTier}!`)
          } else if (data.url) {
            window.location.href = data.url
          }
        },
        onError: (error: Error) => {
          notify("failed to start checkout: " + error.message)
        },
      }
    )
  }

  return (
    <div className="mb-6">
      <h3 className="mb-2 text-text-primary">upgrade to {targetTier}</h3>
      <ul className="mb-4 space-y-1">
        {features.map((feature) => (
          <li key={feature} className="text-text-secondary">
            + {feature}
          </li>
        ))}
      </ul>
      <div className="mb-4 flex items-center gap-2">
        <button
          type="button"
          onClick={() => setBillingInterval("monthly")}
          className={classNames(
            "border px-3 py-1 transition-colors",
            billingInterval === "monthly"
              ? "border-text-primary text-text-primary"
              : "border-border text-text-dim hover:text-text-secondary"
          )}
        >
          {monthlyPrice} / month
        </button>
        <button
          type="button"
          onClick={() => setBillingInterval("yearly")}
          className={classNames(
            "border px-3 py-1 transition-colors",
            billingInterval === "yearly"
              ? "border-text-primary text-text-primary"
              : "border-border text-text-dim hover:text-text-secondary"
          )}
        >
          {yearlyPrice} / year
        </button>
      </div>
      <button
        onClick={handleUpgrade}
        disabled={createCheckoutSession.isPending}
        className="border border-text-primary px-4 py-2 text-text-primary transition-colors hover:bg-text-primary hover:text-background-primary disabled:opacity-50"
      >
        {createCheckoutSession.isPending
          ? "redirecting ..."
          : `upgrade to ${targetTier}`}
      </button>
    </div>
  )
}

export function BillingSettings() {
  const { data: userProfile, isLoading } = useUserProfile()
  const queryClient = useQueryClient()
  const searchParameters = useSearchParams()
  const hasShownSuccessToast = useRef(false)

  const createPortalSession = useCreatePortalSession()

  useEffect(() => {
    if (
      searchParameters.get("billing") === "success" &&
      !hasShownSuccessToast.current
    ) {
      hasShownSuccessToast.current = true
      queryClient.invalidateQueries({ queryKey: queryKeys.userProfile.all })
      const tierName = userProfile?.tier === "developer" ? "Developer" : userProfile?.tier === "pro" ? "Pro" : null
      notify(tierName ? `welcome to ${tierName}` : "subscription activated")
      const url = new URL(window.location.href)
      url.searchParams.delete("billing")
      window.history.replaceState({}, "", url.pathname)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searchParameters, queryClient])

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

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

  function handleManageSubscription() {
    createPortalSession.mutate(undefined, {
      onSuccess: (data) => {
        window.location.href = data.url
      },
      onError: (error: Error) => {
        notify("failed to open billing portal: " + error.message)
      },
    })
  }

  const isPaidTier =
    userProfile.tier === "pro" || userProfile.tier === "developer"
  const isCancelling =
    userProfile.stripeSubscriptionStatus === "active" &&
    isPaidTier &&
    userProfile.stripeCurrentPeriodEnd !== null

  return (
    <div className="px-4 py-3">
      <div className="mb-6">
        <h3 className="mb-2 text-text-primary">current plan</h3>
        <span className="border border-border px-2 py-1 text-text-secondary">
          {userProfile.tier}
        </span>
        {userProfile.stripeSubscriptionStatus && (
          <span className="ml-2 text-text-dim">
            ({userProfile.stripeSubscriptionStatus})
          </span>
        )}
      </div>

      {userProfile.tier === "free" && (
        <>
          <UpgradeCard
            targetTier="pro"
            features={PRO_FEATURES}
            monthlyPrice="$3"
            yearlyPrice="$30"
          />
          <UpgradeCard
            targetTier="developer"
            features={DEVELOPER_FEATURES}
            monthlyPrice="$6"
            yearlyPrice="$60"
          />
        </>
      )}

      {userProfile.tier === "pro" && (
        <>
          <UpgradeCard
            targetTier="developer"
            features={DEVELOPER_FEATURES}
            monthlyPrice="$6"
            yearlyPrice="$60"
          />
          <div className="mb-6">
            {isCancelling && userProfile.stripeCurrentPeriodEnd && (
              <p className="mb-3 text-text-secondary">
                your pro plan is active until{" "}
                {new Date(
                  userProfile.stripeCurrentPeriodEnd
                ).toLocaleDateString()}
              </p>
            )}
            {userProfile.stripeSubscriptionStatus === "past_due" && (
              <p className="mb-3 text-status-error">
                payment failed — please update your payment method
              </p>
            )}
            <button
              onClick={handleManageSubscription}
              disabled={createPortalSession.isPending}
              className="border border-border px-4 py-2 text-text-secondary transition-colors hover:border-text-dim hover:text-text-primary disabled:opacity-50"
            >
              {createPortalSession.isPending
                ? "redirecting ..."
                : "manage subscription"}
            </button>
          </div>
        </>
      )}

      {userProfile.tier === "developer" && (
        <div className="mb-6">
          {isCancelling && userProfile.stripeCurrentPeriodEnd && (
            <p className="mb-3 text-text-secondary">
              your developer plan is active until{" "}
              {new Date(
                userProfile.stripeCurrentPeriodEnd
              ).toLocaleDateString()}
            </p>
          )}
          {userProfile.stripeSubscriptionStatus === "past_due" && (
            <p className="mb-3 text-status-error">
              payment failed — please update your payment method
            </p>
          )}
          <button
            onClick={handleManageSubscription}
            disabled={createPortalSession.isPending}
            className="border border-border px-4 py-2 text-text-secondary transition-colors hover:border-text-dim hover:text-text-primary disabled:opacity-50"
          >
            {createPortalSession.isPending
              ? "redirecting ..."
              : "manage subscription"}
          </button>
        </div>
      )}
    </div>
  )
}
