import { deleteMediaAsset, getMediaAssetById, updateMediaAsset } from "@cms/db"
import { Button } from "@cms/ui/button"
import Link from "next/link"
import { redirect } from "next/navigation"

import { AdminShell } from "@/components/admin-shell"
import { deleteStoredMediaObject } from "@/lib/media/storage"
import { requirePermissionForRoute } from "@/lib/route-guards"

export const dynamic = "force-dynamic"

type SearchParamsInput = Record<string, string | string[] | undefined>

type PageProps = {
  params: Promise<{ id: string }>
  searchParams: Promise<SearchParamsInput>
}

function readFirstValue(value: string | string[] | undefined): string | null {
  if (Array.isArray(value)) {
    return value[0] ?? null
  }

  return value ?? null
}

function readInputString(formData: FormData, field: string): string {
  const value = formData.get(field)
  return typeof value === "string" ? value.trim() : ""
}

function readNullableString(formData: FormData, field: string): string | null {
  const value = readInputString(formData, field)
  return value.length > 0 ? value : null
}

function readNullableInt(formData: FormData, field: string): number | null {
  const value = readInputString(formData, field)

  if (!value) {
    return null
  }

  const parsed = Number.parseInt(value, 10)

  if (!Number.isFinite(parsed)) {
    return null
  }

  return parsed
}

function readTags(formData: FormData): string[] {
  const raw = readInputString(formData, "tags")

  if (!raw) {
    return []
  }

  return raw
    .split(",")
    .map((item) => item.trim())
    .filter((item) => item.length > 0)
}

function redirectWithState(mediaAssetId: string, params: { notice?: string; error?: string }) {
  const query = new URLSearchParams()

  if (params.notice) {
    query.set("notice", params.notice)
  }

  if (params.error) {
    query.set("error", params.error)
  }

  const value = query.toString()
  redirect(value ? `/media/${mediaAssetId}?${value}` : `/media/${mediaAssetId}`)
}

function toLocalDateTimeInputValue(date: Date): string {
  const offset = date.getTimezoneOffset() * 60_000
  return new Date(date.getTime() - offset).toISOString().slice(0, 16)
}

export default async function MediaAssetEditorPage({ params, searchParams }: PageProps) {
  const role = await requirePermissionForRoute({
    nextPath: "/media",
    permission: "media:read",
    scope: "team",
  })
  const resolvedParams = await params
  const mediaAssetId = resolvedParams.id

  const [resolvedSearchParams, asset] = await Promise.all([
    searchParams,
    getMediaAssetById(mediaAssetId),
  ])

  if (!asset) {
    redirect("/media?error=Media+asset+not+found")
  }
  const mediaAsset = asset

  const notice = readFirstValue(resolvedSearchParams.notice)
  const error = readFirstValue(resolvedSearchParams.error)
  const previewUrl = mediaAsset.storageKey ? `/api/media/file/${mediaAsset.id}` : null
  const isImage = Boolean(mediaAsset.mimeType?.startsWith("image/"))
  const isVideo = Boolean(mediaAsset.mimeType?.startsWith("video/"))

  async function updateMediaAssetAction(formData: FormData) {
    "use server"

    await requirePermissionForRoute({
      nextPath: "/media",
      permission: "media:write",
      scope: "team",
    })

    try {
      await updateMediaAsset({
        id: mediaAssetId,
        title: readInputString(formData, "title"),
        type: readInputString(formData, "type"),
        description: readNullableString(formData, "description"),
        altText: readNullableString(formData, "altText"),
        source: readNullableString(formData, "source"),
        copyright: readNullableString(formData, "copyright"),
        author: readNullableString(formData, "author"),
        tags: readTags(formData),
        mimeType: readNullableString(formData, "mimeType"),
        width: readNullableInt(formData, "width"),
        height: readNullableInt(formData, "height"),
        sizeBytes: readNullableInt(formData, "sizeBytes"),
        isPublished: readInputString(formData, "isPublished") === "true",
      })
    } catch {
      redirectWithState(mediaAssetId, {
        error: "Failed to update media asset. Validate values and try again.",
      })
    }

    redirectWithState(mediaAssetId, { notice: "Media asset updated." })
  }

  async function deleteMediaAssetAction() {
    "use server"

    await requirePermissionForRoute({
      nextPath: "/media",
      permission: "media:write",
      scope: "team",
    })

    try {
      if (mediaAsset.storageKey) {
        await deleteStoredMediaObject(mediaAsset.storageKey)
      }

      await deleteMediaAsset(mediaAssetId)
    } catch {
      redirectWithState(mediaAssetId, {
        error:
          "Failed to delete media asset and file from storage. Check storage config and links.",
      })
    }

    redirect("/media?notice=Media+asset+deleted")
  }

  return (
    <AdminShell
      role={role}
      activePath="/media"
      badge="Admin App"
      title="Media Asset"
      description="View, edit, and delete uploaded media metadata."
    >
      {notice ? (
        <section className="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
          {notice}
        </section>
      ) : null}

      {error ? (
        <section className="rounded-xl border border-red-300 bg-red-50 px-4 py-3 text-sm text-red-800">
          {error}
        </section>
      ) : null}

      <section className="rounded-xl border border-neutral-200 p-6">
        <h3 className="text-lg font-medium">Preview</h3>
        <p className="mt-1 text-sm text-neutral-600">
          {mediaAsset.mimeType ? `MIME: ${mediaAsset.mimeType}` : "MIME: unknown"}
        </p>

        <div className="mt-4 rounded-lg border border-neutral-200 bg-neutral-50 p-3">
          {!previewUrl ? (
            <p className="text-sm text-neutral-600">
              No stored file is linked for this media asset.
            </p>
          ) : isImage ? (
            // biome-ignore lint/performance/noImgElement: Auth-protected media preview requires direct browser request with session cookies.
            <img
              src={previewUrl}
              alt={mediaAsset.altText || mediaAsset.title}
              className="max-h-[26rem] w-auto rounded border border-neutral-200 bg-white"
            />
          ) : isVideo ? (
            // biome-ignore lint/a11y/useMediaCaption: Preview uses source assets without guaranteed caption tracks.
            <video
              src={previewUrl}
              controls
              preload="metadata"
              className="max-h-[26rem] w-full rounded border border-neutral-200 bg-black"
            />
          ) : (
            <p className="text-sm text-neutral-700">
              Inline preview is not available for this media type.
            </p>
          )}
        </div>

        {previewUrl ? (
          <a
            href={previewUrl}
            target="_blank"
            rel="noreferrer"
            className="mt-3 inline-block text-sm text-neutral-700 underline underline-offset-2"
          >
            Open raw media file
          </a>
        ) : null}
      </section>

      <section className="rounded-xl border border-neutral-200 p-6">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div>
            <h2 className="text-xl font-medium">{mediaAsset.title}</h2>
            <p className="mt-1 text-xs text-neutral-600">ID: {mediaAsset.id}</p>
          </div>
          <Link href="/media" className="text-sm text-neutral-700 underline underline-offset-2">
            Back to media list
          </Link>
        </div>

        <form action={updateMediaAssetAction} className="mt-6 space-y-3">
          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Title</span>
              <input
                name="title"
                defaultValue={mediaAsset.title}
                required
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Type</span>
              <select
                name="type"
                defaultValue={mediaAsset.type}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              >
                <option value="artwork">artwork</option>
                <option value="banner">banner</option>
                <option value="promotion">promotion</option>
                <option value="video">video</option>
                <option value="gif">gif</option>
                <option value="generic">generic</option>
              </select>
            </label>
          </div>

          <label className="space-y-1">
            <span className="text-xs text-neutral-600">Description</span>
            <textarea
              name="description"
              rows={3}
              defaultValue={mediaAsset.description ?? ""}
              className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
            />
          </label>

          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Alt text</span>
              <input
                name="altText"
                defaultValue={mediaAsset.altText ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Author</span>
              <input
                name="author"
                defaultValue={mediaAsset.author ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Source</span>
              <input
                name="source"
                defaultValue={mediaAsset.source ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Copyright</span>
              <input
                name="copyright"
                defaultValue={mediaAsset.copyright ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>

          <div className="grid gap-3 md:grid-cols-3">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">MIME type</span>
              <input
                name="mimeType"
                defaultValue={mediaAsset.mimeType ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Width</span>
              <input
                name="width"
                type="number"
                min={1}
                defaultValue={mediaAsset.width ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Height</span>
              <input
                name="height"
                type="number"
                min={1}
                defaultValue={mediaAsset.height ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Size (bytes)</span>
              <input
                name="sizeBytes"
                type="number"
                min={0}
                defaultValue={mediaAsset.sizeBytes ?? ""}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Tags (comma-separated)</span>
              <input
                name="tags"
                defaultValue={mediaAsset.tags.join(", ")}
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>

          <label className="inline-flex items-center gap-2 text-sm text-neutral-700">
            <input
              type="checkbox"
              name="isPublished"
              value="true"
              defaultChecked={mediaAsset.isPublished}
              className="size-4"
            />
            Published
          </label>

          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Storage key</span>
              <input
                value={mediaAsset.storageKey ?? "-"}
                readOnly
                className="w-full rounded border border-neutral-200 bg-neutral-50 px-3 py-2 text-xs text-neutral-600"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Last updated</span>
              <input
                value={toLocalDateTimeInputValue(mediaAsset.updatedAt)}
                readOnly
                className="w-full rounded border border-neutral-200 bg-neutral-50 px-3 py-2 text-xs text-neutral-600"
              />
            </label>
          </div>

          <Button type="submit">Save changes</Button>
        </form>
      </section>

      <section className="rounded-xl border border-red-300 bg-red-50 p-6">
        <h3 className="text-lg font-medium text-red-800">Danger Zone</h3>
        <p className="mt-1 text-sm text-red-700">
          Deleting this media asset is permanent. Any linked artwork rendition references will also
          be removed.
        </p>
        <form action={deleteMediaAssetAction} className="mt-4">
          <Button type="submit" variant="secondary" className="border border-red-300 text-red-800">
            Delete media asset
          </Button>
        </form>
      </section>
    </AdminShell>
  )
}
