'use client'

import { useState, useEffect, useCallback, useRef } from 'react'
import {
  AlertTriangle,
  Calendar,
  Eye,
  EyeOff,
  Save,
  Copy,
  Loader2,
  Clock,
  Share2,
  XCircle,
} from 'lucide-react'
import { toast } from 'sonner'
import { FieldRenderer } from '../fields/FieldRenderer.js'
import { RelationshipField } from '../fields/RelationshipField.js'
import { Button } from '../components/ui/Button.js'
import { Badge } from '../components/ui/Badge.js'
import { LivePreview } from '../components/LivePreview.js'
import { VersionHistory } from '../components/VersionHistory.js'
import { PresenceIndicator } from '../components/PresenceIndicator.js'
import { SEOPanel } from '../components/SEOPanel.js'
import type { SEOData } from '../components/SEOPanel.js'
import { SchedulePublishDialog } from '../components/SchedulePublishDialog.js'
import { SharePreviewLinkDialog } from '../components/SharePreviewLinkDialog.js'
import { cmsApi } from '../lib/api.js'

export interface DocumentEditProps {
  collectionSlug: string
  documentId?: string
  config: any
  onNavigate?: (path: string) => void
}

export function DocumentEdit({
  collectionSlug,
  documentId,
  config,
  onNavigate,
}: DocumentEditProps) {
  const isNew = !documentId
  const [values, setValues] = useState<Record<string, any>>({})
  const [initialValues, setInitialValues] = useState<Record<string, any>>({})
  const [seoData, setSeoData] = useState<SEOData>({})
  const [initialSeoData, setInitialSeoData] = useState<SEOData>({})
  const [layoutAssignments, setLayoutAssignments] = useState<Record<string, string>>({})
  const [initialLayoutAssignments, setInitialLayoutAssignments] = useState<Record<string, string>>(
    {},
  )
  const [saving, setSaving] = useState(false)
  const [loading, setLoading] = useState(!isNew)
  const [showPreview, setShowPreview] = useState(false)
  const [showVersions, setShowVersions] = useState(false)
  const [showSchedule, setShowSchedule] = useState(false)
  const [showShareLink, setShowShareLink] = useState(false)
  const [docStatus, setDocStatus] = useState<string>('DRAFT')
  const [scheduledAt, setScheduledAt] = useState<string | null>(null)
  const [scheduledUnpublishAt, setScheduledUnpublishAt] = useState<string | null>(null)
  const hasLoadedRef = useRef(false)

  const collections = config?.collections
  const collection = Array.isArray(collections)
    ? collections.find((c: any) => c.slug === collectionSlug)
    : collections?.[collectionSlug]

  const layoutConfig = config?.layout
  const layoutRegions: Array<{ name: string; collection: string; label: string }> =
    layoutConfig?.regions
      ? Object.entries(layoutConfig.regions).map(([name, region]: [string, any]) => ({
          name,
          collection: region.collection,
          label: region.label ?? name.charAt(0).toUpperCase() + name.slice(1),
        }))
      : []
  const hasLayout =
    layoutRegions.length > 0 && (collection?.type === 'page' || collection?.urlPrefix !== undefined)

  const previewUrl = collection?.admin?.preview ? collection.admin.preview({}) : undefined
  const fields: any[] = collection?.fields
    ? Array.isArray(collection.fields)
      ? collection.fields
      : Object.entries(collection.fields).map(([name, def]: [string, any]) => ({ name, ...def }))
    : []

  const useAsTitleField = collection?.admin?.useAsTitle ?? 'title'
  const displayTitle = isNew
    ? `New ${collection?.labels?.singular ?? collectionSlug}`
    : `Edit ${values[useAsTitleField] ?? 'Document'}`

  const isDirty =
    JSON.stringify(values) !== JSON.stringify(initialValues) ||
    JSON.stringify(seoData) !== JSON.stringify(initialSeoData) ||
    JSON.stringify(layoutAssignments) !== JSON.stringify(initialLayoutAssignments)

  useEffect(() => {
    if (!isNew && documentId && !hasLoadedRef.current) {
      hasLoadedRef.current = true
      loadDocument()
    }
  }, [documentId, isNew])

  useEffect(() => {
    if (!isDirty) return
    const handler = (e: BeforeUnloadEvent) => {
      e.preventDefault()
    }
    window.addEventListener('beforeunload', handler)
    return () => window.removeEventListener('beforeunload', handler)
  }, [isDirty])

  const SEO_FIELDS: (keyof SEOData)[] = [
    'metaTitle',
    'metaDescription',
    'focusKeyphrase',
    'keyTakeaway',
    'canonical',
    'robotsPolicy',
    'noIndex',
    'noFollow',
    'ogTitle',
    'ogDescription',
    'ogImage',
    'twitterTitle',
    'twitterDescription',
    'twitterImage',
    'isCornerstone',
    'schemaType',
  ]

  async function loadDocument() {
    setLoading(true)
    const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`)
    if (res.data) {
      const doc = res.data
      const docData = doc.data && typeof doc.data === 'object' ? doc.data : {}
      const merged = {
        ...docData,
        title: doc.title ?? docData.title,
        slug: doc.slug ?? docData.slug,
      }
      setValues(merged)
      setInitialValues(merged)
      setDocStatus(doc.status ?? 'DRAFT')
      setScheduledAt(doc.scheduledAt ?? null)
      setScheduledUnpublishAt(doc.scheduledUnpublishAt ?? null)

      const loadedSeo: SEOData = {}
      for (const key of SEO_FIELDS) {
        if (docData[key] !== undefined) {
          ;(loadedSeo as any)[key] = docData[key]
        }
      }
      setSeoData(loadedSeo)
      setInitialSeoData(loadedSeo)

      if (docData._layout && typeof docData._layout === 'object') {
        const loaded = docData._layout as Record<string, string>
        setLayoutAssignments(loaded)
        setInitialLayoutAssignments(loaded)
      }
    } else if (res.error) {
      toast.error(`Failed to load document: ${res.error}`)
    }
    setLoading(false)
  }

  function handleFieldChange(name: string, value: any) {
    setValues((prev) => ({ ...prev, [name]: value }))
  }

  async function handleSave() {
    setSaving(true)
    const layoutPayload =
      Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
    const payload = { ...values, ...seoData, ...layoutPayload }
    try {
      if (isNew) {
        const res = await cmsApi<any>(`/collections/${collectionSlug}`, {
          method: 'POST',
          body: JSON.stringify(payload),
        })
        if (res.error) {
          toast.error(res.error)
        } else {
          toast.success('Document created')
          const newId = res.data?.id
          setInitialValues(values)
          setInitialSeoData(seoData)
          setInitialLayoutAssignments(layoutAssignments)
          if (newId && onNavigate) {
            onNavigate(`/${collectionSlug}/${newId}`)
          }
        }
      } else {
        const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
          method: 'PUT',
          body: JSON.stringify(payload),
        })
        if (res.error) {
          toast.error(res.error)
        } else {
          toast.success('Changes saved')
          setInitialValues(values)
          setInitialSeoData(seoData)
          setInitialLayoutAssignments(layoutAssignments)
          if (res.data?.status) setDocStatus(res.data.status)
        }
      }
    } catch {
      toast.error('An unexpected error occurred')
    }
    setSaving(false)
  }

  async function handlePublish() {
    if (isNew) return
    setSaving(true)
    const layoutPayload =
      Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
    const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
      method: 'PUT',
      body: JSON.stringify({ ...values, ...seoData, ...layoutPayload, status: 'PUBLISHED' }),
    })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Document published')
      setDocStatus('PUBLISHED')
      setInitialValues(values)
      setInitialSeoData(seoData)
      setInitialLayoutAssignments(layoutAssignments)
    }
    setSaving(false)
  }

  async function handleUnpublish() {
    if (isNew) return
    setSaving(true)
    const layoutPayload =
      Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
    const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
      method: 'PUT',
      body: JSON.stringify({ ...values, ...seoData, ...layoutPayload, status: 'DRAFT' }),
    })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Document unpublished')
      setDocStatus('DRAFT')
      setInitialValues(values)
      setInitialSeoData(seoData)
      setInitialLayoutAssignments(layoutAssignments)
    }
    setSaving(false)
  }

  async function handleDuplicate() {
    if (isNew || !documentId) return
    const res = await cmsApi<any>(`/collections/${collectionSlug}`, {
      method: 'POST',
      body: JSON.stringify({
        ...values,
        title: values.title ? `${values.title} (Copy)` : undefined,
        slug: values.slug ? `${values.slug}-copy` : undefined,
      }),
    })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Document duplicated')
      const newId = res.data?.id
      if (newId && onNavigate) {
        onNavigate(`/${collectionSlug}/${newId}`)
      }
    }
  }

  const mainFields = fields.filter(
    (f: any) => !['status', 'publishedAt', 'featured', 'featuredImage'].includes(f.name),
  )
  const sidebarFields = fields.filter((f: any) =>
    ['publishedAt', 'featured', 'featuredImage'].includes(f.name),
  )

  const contentField = fields.find(
    (f: any) => f.type === 'richText' || f.name === 'content' || f.name === 'body',
  )
  const htmlContent = contentField ? (values[contentField.name] ?? '') : ''
  const docSlug = values.slug ?? ''

  const statusColor =
    docStatus === 'PUBLISHED'
      ? 'bg-success/10 text-success'
      : docStatus === 'SCHEDULED'
        ? 'bg-info/10 text-info'
        : 'bg-warning/10 text-warning'

  if (loading) {
    return (
      <div className="flex min-h-[300px] items-center justify-center">
        <Loader2 className="text-muted-foreground h-8 w-8 animate-spin" />
      </div>
    )
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <h1 className="text-2xl font-medium">{displayTitle}</h1>
          <span
            className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${statusColor}`}
          >
            {docStatus}
          </span>
          {documentId && <PresenceIndicator documentId={documentId} />}
          {isDirty && <span className="text-warning text-xs font-medium">Unsaved changes</span>}
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => setShowPreview((v) => !v)}
            className="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm text-[var(--muted-foreground)] hover:bg-[var(--muted)] hover:text-[var(--foreground)]"
            title={showPreview ? 'Hide preview' : 'Show preview'}
          >
            {showPreview ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
            Preview
          </button>
          {!isNew && (
            <>
              <button
                onClick={() => setShowShareLink(true)}
                className="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm text-[var(--muted-foreground)] hover:bg-[var(--muted)] hover:text-[var(--foreground)]"
                title="Share a signed preview link for the current draft"
              >
                <Share2 className="h-4 w-4" />
                Share preview
              </button>
              <button
                onClick={() => setShowVersions(true)}
                className="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm text-[var(--muted-foreground)] hover:bg-[var(--muted)] hover:text-[var(--foreground)]"
                title="Version history"
              >
                <Clock className="h-4 w-4" />
                History
              </button>
              <button
                onClick={handleDuplicate}
                className="inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm text-[var(--muted-foreground)] hover:bg-[var(--muted)] hover:text-[var(--foreground)]"
                title="Duplicate this document"
              >
                <Copy className="h-4 w-4" />
                Duplicate
              </button>
            </>
          )}
        </div>
      </div>

      <div className={showPreview ? 'grid grid-cols-2 gap-6' : ''}>
        <div className="space-y-6">
          {fields.length === 0 ? (
            <div className="flex flex-col items-center justify-center rounded-lg border border-[var(--border)] py-16 text-center">
              <div className="bg-muted mb-4 flex h-12 w-12 items-center justify-center rounded-full">
                <AlertTriangle className="text-muted-foreground h-6 w-6" />
              </div>
              <h3 className="text-foreground mb-1 text-sm font-medium">
                Collection schema not found
              </h3>
              <p className="text-muted-foreground text-sm">
                No fields are defined for this collection.
              </p>
            </div>
          ) : (
            <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
              <div className="space-y-6 lg:col-span-2">
                {mainFields.map((field: any) => (
                  <FieldRenderer
                    key={field.name}
                    field={field}
                    value={values[field.name]}
                    onChange={(val) => handleFieldChange(field.name, val)}
                  />
                ))}
              </div>

              <div className="space-y-6">
                <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
                  <h3 className="mb-4 font-medium">Status</h3>
                  <div className="space-y-3">
                    {!isNew && docStatus === 'DRAFT' && (
                      <Button
                        variant="primary"
                        className="w-full"
                        onClick={handlePublish}
                        loading={saving}
                      >
                        Publish
                      </Button>
                    )}
                    {!isNew && docStatus === 'PUBLISHED' && (
                      <Button
                        variant="secondary"
                        className="w-full"
                        onClick={handleUnpublish}
                        loading={saving}
                      >
                        Unpublish
                      </Button>
                    )}
                    {!isNew && (
                      <button
                        onClick={() => setShowSchedule(true)}
                        className="border-border bg-card text-foreground hover:bg-accent inline-flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium"
                      >
                        <Calendar className="h-4 w-4" />
                        {scheduledAt || scheduledUnpublishAt ? 'Reschedule' : 'Schedule'}
                      </button>
                    )}
                    {!isNew && (scheduledAt || scheduledUnpublishAt) && (
                      <div className="border-info/30 bg-info/10 text-foreground space-y-1 rounded-md border px-3 py-2 text-xs">
                        {scheduledAt && (
                          <div className="flex items-center gap-1.5">
                            <Calendar className="h-3.5 w-3.5" />
                            Publishes {new Date(scheduledAt).toLocaleString()}
                          </div>
                        )}
                        {scheduledUnpublishAt && (
                          <div className="flex items-center gap-1.5">
                            <XCircle className="h-3.5 w-3.5" />
                            Unpublishes {new Date(scheduledUnpublishAt).toLocaleString()}
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                </div>

                {sidebarFields.length > 0 && (
                  <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
                    <h3 className="mb-4 font-medium">Metadata</h3>
                    {sidebarFields.map((field: any) => (
                      <div key={field.name} className="mb-4">
                        <FieldRenderer
                          field={field}
                          value={values[field.name]}
                          onChange={(val) => handleFieldChange(field.name, val)}
                        />
                      </div>
                    ))}
                  </div>
                )}

                <SEOPanel
                  title={values[useAsTitleField] ?? values.title ?? ''}
                  slug={docSlug}
                  content={htmlContent}
                  seoData={seoData}
                  onChange={setSeoData}
                  siteUrl={config?.siteUrl}
                />

                {hasLayout && (
                  <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
                    <h3 className="mb-1 font-medium">Layout</h3>
                    <p className="mb-4 text-xs text-[var(--muted-foreground)]">
                      Assign header/footer variants. Child pages inherit from ancestors.
                    </p>
                    <div className="space-y-4">
                      {layoutRegions.map((region) => (
                        <div key={region.name}>
                          <RelationshipField
                            label={region.label}
                            value={layoutAssignments[region.name] ?? ''}
                            onChange={(val) => {
                              setLayoutAssignments((prev) => {
                                const next = { ...prev }
                                if (val && typeof val === 'string') {
                                  next[region.name] = val
                                } else {
                                  delete next[region.name]
                                }
                                return next
                              })
                            }}
                            relationTo={region.collection}
                            helpText={
                              !layoutAssignments[region.name]
                                ? 'Inheriting from parent page or site default'
                                : undefined
                            }
                          />
                          {layoutAssignments[region.name] && (
                            <button
                              type="button"
                              onClick={() => {
                                setLayoutAssignments((prev) => {
                                  const next = { ...prev }
                                  delete next[region.name]
                                  return next
                                })
                              }}
                              className="mt-1 text-xs text-[var(--primary)] hover:underline"
                            >
                              Clear override (inherit from parent)
                            </button>
                          )}
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            </div>
          )}

          <div className="sticky bottom-0 flex items-center justify-end gap-3 border-t border-[var(--border)] bg-[var(--background)] px-4 py-3">
            <Button variant="secondary" onClick={() => onNavigate?.(`/${collectionSlug}`)}>
              Cancel
            </Button>
            <Button variant="primary" loading={saving} onClick={handleSave} data-shortcut="save">
              <Save className="mr-1.5 h-4 w-4" />
              {isNew ? 'Create' : 'Save Changes'}
            </Button>
          </div>
        </div>

        {showPreview && (
          <LivePreview
            collection={collectionSlug}
            documentId={documentId}
            previewUrl={previewUrl}
            values={values}
            onClose={() => setShowPreview(false)}
          />
        )}
      </div>

      {!isNew && documentId && (
        <VersionHistory
          collectionSlug={collectionSlug}
          documentId={documentId}
          open={showVersions}
          onClose={() => setShowVersions(false)}
          onRestore={(data) => {
            const restoredData = data as Record<string, any>
            setValues(restoredData)
            setInitialValues(restoredData)
          }}
        />
      )}

      {!isNew && documentId && (
        <SchedulePublishDialog
          collectionSlug={collectionSlug}
          documentId={documentId}
          scheduledAt={scheduledAt}
          scheduledUnpublishAt={scheduledUnpublishAt}
          open={showSchedule}
          onClose={() => setShowSchedule(false)}
          onScheduled={(next) => {
            setDocStatus(next.status)
            setScheduledAt(next.scheduledAt)
            setScheduledUnpublishAt(next.scheduledUnpublishAt)
          }}
        />
      )}

      {!isNew && documentId && (
        <SharePreviewLinkDialog
          collectionSlug={collectionSlug}
          documentId={documentId}
          documentSlug={docSlug}
          siteUrl={config?.siteUrl}
          urlPrefix={collection?.urlPrefix ?? collectionSlug}
          open={showShareLink}
          onClose={() => setShowShareLink(false)}
        />
      )}
    </div>
  )
}
