import { useEffect, useState } from 'react'
import { Link, useParams, useNavigate } from 'react-router-dom'
import { SearchableSelect } from '../components/SearchableSelect'
import { ImageCropper } from '../components/ImageCropper'
import { ImageUploader } from '../components/ImageUploader'
import { TagInput } from '../components/TagInput'
import { RichTextEditor } from '../components/RichTextEditor'
import { Breadcrumbs } from '../components/Breadcrumbs'
import { useToast } from '../context/ToastContext'
import { ApiError } from '../lib/api'
import {
  listPortfolioCategories,
  mapPortfolioCategoryToUi,
} from '../services/portfolioCategoryService'
import {
  resolveDataUrlToMediaId,
  resolveDataUrlsToMediaIds,
  resolveHtmlEmbeddedDataUrls,
} from '../services/mediaService'
import {
  createPortfolio,
  getPortfolio,
  mapPortfolioApiToFormState,
  updatePortfolio,
} from '../services/portfolioService'
import type { Category } from '../types/category'
import { flattenCategories } from '../utils/categories'
import pageStyles from '../components/PageContent.module.css'
import styles from './AddNewProductPage.module.css'

type TitleImageAspectId = 'square' | '3:2' | '16:9' | '9:16'

const TITLE_IMAGE_ASPECTS: {
  id: TitleImageAspectId
  label: string
  aspect: number
}[] = [
  { id: 'square', label: 'Square', aspect: 1 },
  { id: '3:2', label: '3:2', aspect: 3 / 2 },
  { id: '16:9', label: '16:9', aspect: 16 / 9 },
  { id: '9:16', label: '9:16 (Reel)', aspect: 9 / 16 },
]

export function AddNewPortfolioPage() {
  const { id } = useParams()
  const navigate = useNavigate()
  const { showToast } = useToast()
  const isEdit = Boolean(id)

  const [categories, setCategories] = useState<Category[]>([])
  const [categoryId, setCategoryId] = useState('')
  const [titleFa, setTitleFa] = useState('')
  const [titleEn, setTitleEn] = useState('')
  const [abstract, setAbstract] = useState('')
  const [mainTextHtml, setMainTextHtml] = useState('')
  const [titleImage, setTitleImage] = useState<string | null>(null)
  const [titleImageAspect, setTitleImageAspect] = useState<TitleImageAspectId>('3:2')
  const [images, setImages] = useState<string[]>([])
  const [tags, setTags] = useState<string[]>([])
  const [featuredMediaId, setFeaturedMediaId] = useState<string | null>(null)
  const [galleryMediaIds, setGalleryMediaIds] = useState<string[]>([])
  const [loaded, setLoaded] = useState(!isEdit)
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [error, setError] = useState('')

  const categoryOptions = flattenCategories(categories)
  const selectedAspect =
    TITLE_IMAGE_ASPECTS.find((option) => option.id === titleImageAspect)?.aspect ?? 3 / 2

  useEffect(() => {
    const controller = new AbortController()

    async function loadCategories() {
      try {
        const items = await listPortfolioCategories(controller.signal)
        setCategories(items.map(mapPortfolioCategoryToUi))
      } catch (err) {
        if (err instanceof DOMException && err.name === 'AbortError') return
        if (err instanceof ApiError) {
          setError(err.message)
        } else {
          setError('Unable to load categories.')
        }
      }
    }

    void loadCategories()
    return () => controller.abort()
  }, [])

  useEffect(() => {
    if (!isEdit || !id) return

    const controller = new AbortController()

    async function loadPortfolio() {
      setError('')
      try {
        const portfolio = await getPortfolio(id!, controller.signal)
        const form = mapPortfolioApiToFormState(portfolio)
        setCategoryId(form.categoryId)
        setTitleFa(form.titleFa)
        setTitleEn(form.titleEn)
        setAbstract(form.abstract)
        setMainTextHtml(form.mainTextHtml)
        setTitleImage(form.titleImage)
        setImages(form.images)
        setTags(form.tags)
        setFeaturedMediaId(form.featuredMediaId)
        setGalleryMediaIds(form.galleryMediaIds)
        setLoaded(true)
      } catch (err) {
        if (err instanceof DOMException && err.name === 'AbortError') return
        navigate('/portfolios/list', { replace: true })
      }
    }

    void loadPortfolio()
    return () => controller.abort()
  }, [isEdit, id, navigate])

  if (!loaded) return null

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()
    setIsSubmitting(true)
    setError('')

    try {
      const nextFeaturedMediaId = await resolveDataUrlToMediaId(
        titleImage,
        'portfolio-title-image.jpg',
        featuredMediaId,
      )
      const resolvedMainTextHtml = await resolveHtmlEmbeddedDataUrls(mainTextHtml)
      const nextGalleryMediaIds = await resolveDataUrlsToMediaIds(images, galleryMediaIds)

      if (titleImage?.startsWith('data:') && !nextFeaturedMediaId) {
        setError('Unable to upload title image. Please try again.')
        setIsSubmitting(false)
        return
      }

      const payload = {
        titleFa: titleFa.trim(),
        titleEn: titleEn.trim() || undefined,
        abstract: abstract.trim(),
        mainTextHtml: resolvedMainTextHtml,
        categoryId: categoryId || undefined,
        featuredMediaId: nextFeaturedMediaId ?? undefined,
        galleryMediaIds: nextGalleryMediaIds,
        tags,
        status: 'published' as const,
      }

      if (isEdit && id) {
        await updatePortfolio(id, {
          ...payload,
          categoryId: categoryId || null,
          featuredMediaId: nextFeaturedMediaId,
        })
        showToast('Portfolio updated.', 'success')
      } else {
        await createPortfolio(payload)
        showToast('Portfolio created.', 'success')
      }

      navigate('/portfolios/list')
    } catch (err) {
      if (err instanceof ApiError) {
        setError(err.message)
      } else if (err instanceof Error) {
        setError(err.message)
      } else {
        setError('Unable to save portfolio.')
      }
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <main className={pageStyles.content}>
      <Breadcrumbs
        items={
          isEdit
            ? [
                { label: 'Dashboard', href: '/' },
                { label: 'Portfolios', href: '/portfolios' },
                { label: 'My Portfolios', href: '/portfolios/list' },
                { label: 'Edit Portfolio' },
              ]
            : [
                { label: 'Dashboard', href: '/' },
                { label: 'Portfolios', href: '/portfolios' },
                { label: 'Add New Portfolio' },
              ]
        }
      />
      <div className={pageStyles.pageHeader}>
        <div>
          <h2 className={pageStyles.pageTitle}>
            {isEdit ? 'Edit Portfolio' : 'Add New Portfolio'}
          </h2>
          <p className={pageStyles.pageSubtitle}>
            {isEdit
              ? 'Update portfolio details and save changes.'
              : 'Create and publish a new portfolio project.'}
          </p>
        </div>
      </div>

      {error && (
        <div className={styles.error} role="alert">
          {error}
        </div>
      )}

      <form className={styles.form} onSubmit={handleSubmit}>
        <div className={styles.formGrid}>
          <div className={`${styles.field} ${styles.col3} ${styles.thumbnailField}`}>
            <label>Title Image</label>
            <div
              className={styles.aspectOptions}
              role="radiogroup"
              aria-label="Title image aspect ratio"
            >
              {TITLE_IMAGE_ASPECTS.map((option) => (
                <button
                  key={option.id}
                  type="button"
                  role="radio"
                  aria-checked={titleImageAspect === option.id}
                  className={`${styles.aspectChip} ${
                    titleImageAspect === option.id ? styles.aspectChipSelected : ''
                  }`}
                  onClick={() => {
                    if (option.id === titleImageAspect) return
                    setTitleImageAspect(option.id)
                    // Aspect only applies during crop — clear so the user re-crops
                    if (titleImage) {
                      setTitleImage(null)
                      setFeaturedMediaId(null)
                    }
                  }}
                  disabled={isSubmitting}
                >
                  {option.label}
                </button>
              ))}
            </div>
            <ImageCropper
              value={titleImage}
              onChange={setTitleImage}
              aspect={selectedAspect}
              uploadLabel="Upload title image"
              hint="Click to select, then crop"
              changeLabel="Change title image"
            />
          </div>

          <div className={styles.formColumn}>
            <div className={styles.field}>
              <label>Category</label>
              <SearchableSelect
                options={categoryOptions}
                value={categoryId}
                onChange={setCategoryId}
                placeholder="Search and select category..."
              />
            </div>

            <div className={styles.titleRow}>
              <div className={styles.field}>
                <label htmlFor="portfolio-title-fa">Title (FA)</label>
                <input
                  id="portfolio-title-fa"
                  name="titleFa"
                  type="text"
                  dir="rtl"
                  lang="fa"
                  className="faText"
                  placeholder="عنوان فارسی"
                  value={titleFa}
                  onChange={(e) => setTitleFa(e.target.value)}
                  required
                  disabled={isSubmitting}
                />
              </div>

              <div className={styles.field}>
                <label htmlFor="portfolio-title-en">Title (EN)</label>
                <input
                  id="portfolio-title-en"
                  name="titleEn"
                  type="text"
                  dir="ltr"
                  placeholder="English title"
                  value={titleEn}
                  onChange={(e) => setTitleEn(e.target.value)}
                  disabled={isSubmitting}
                />
              </div>
            </div>

            <div className={styles.field}>
              <label htmlFor="portfolio-abstract">Abstract</label>
              <textarea
                id="portfolio-abstract"
                name="abstract"
                rows={4}
                placeholder="Short summary shown in portfolio listings"
                value={abstract}
                onChange={(e) => setAbstract(e.target.value)}
                required
                disabled={isSubmitting}
              />
            </div>

            <div className={styles.field}>
              <label>Main Text</label>
              <RichTextEditor
                value={mainTextHtml}
                onChange={setMainTextHtml}
                placeholder="Full portfolio content with formatting and images..."
                allowImages
                editorMinHeight={280}
              />
            </div>
          </div>

          <div className={`${styles.field} ${styles.col12}`}>
            <label>Image Gallery</label>
            <ImageUploader images={images} onChange={setImages} />
          </div>

          <div className={`${styles.field} ${styles.col12}`}>
            <label>Tags</label>
            <TagInput tags={tags} onChange={setTags} />
          </div>
        </div>

        <div className={styles.actions}>
          <Link to="/portfolios/list" className={styles.cancelBtn}>
            Cancel
          </Link>
          <button type="submit" className={styles.submitBtn} disabled={isSubmitting}>
            {isSubmitting ? 'Saving...' : isEdit ? 'Update Portfolio' : 'Save Portfolio'}
          </button>
        </div>
      </form>
    </main>
  )
}
