"use client";

import type { PortfolioProjectViewMode, PortfolioSectionType } from "@prisma/client";
import {
  ArrowDown,
  ArrowUp,
  CalendarDays,
  FolderTree,
  Layers3,
  Link2,
  Plus,
  Text,
  Trash2,
  UserRound,
} from "lucide-react";
import { type ReactNode, useEffect, useRef, useState } from "react";

import { MediaFieldPicker, type MediaFieldState } from "@/components/root/media-field-picker";
import { AppCard } from "@/components/ui/app-card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { moveArrayItem } from "@/lib/array";
import type { MediaOption } from "@/lib/media";
import type { PortfolioCategoryView, PortfolioProjectView } from "@/lib/portfolio";
import { cn } from "@/lib/utils";

type SectionFormValue = {
  id?: string;
  type: PortfolioSectionType;
  titleAr: string;
  titleEn: string;
  titleDe: string;
  bodyAr: string;
  bodyEn: string;
  bodyDe: string;
  imagePath: string;
  media: MediaFieldState;
  linkUrl: string;
  sortOrder: number;
};

type AssetFormValue = {
  id?: string;
  kind: "IMAGE";
  filePath: string;
  fileFieldName: string;
  media: MediaFieldState;
  altAr: string;
  altEn: string;
  altDe: string;
  sortOrder: number;
};

type ProjectFormState = {
  categoryId: string;
  slug: string;
  clientName: string;
  projectYear: string;
  previewUrl: string;
  sortOrder: string;
  viewMode: PortfolioProjectViewMode;
  isFeatured: boolean;
  isPublished: boolean;
  titleAr: string;
  titleEn: string;
  titleDe: string;
  serviceLabelAr: string;
  serviceLabelEn: string;
  serviceLabelDe: string;
  summaryAr: string;
  summaryEn: string;
  summaryDe: string;
};

type PortfolioProjectFormProps = {
  action: (formData: FormData) => void | Promise<void>;
  categories: PortfolioCategoryView[];
  mediaOptions: MediaOption[];
  project?: PortfolioProjectView | null;
  formId: string;
  redirectPath: string;
};

const locales = [
  { suffix: "Ar" as const, label: "Arabic" },
  { suffix: "En" as const, label: "English" },
  { suffix: "De" as const, label: "German" },
] as const;

const sectionTypeOptions: PortfolioSectionType[] = [
  "RICH_TEXT",
  "GALLERY",
  "STATS",
  "DELIVERABLES",
  "LINK",
];

const viewModeOptions: Array<{
  value: PortfolioProjectViewMode;
  label: string;
  description: string;
}> = [
  { value: "GRID", label: "Grid", description: "Balanced modular layout." },
  { value: "STORY", label: "Story", description: "Narrative section flow." },
  { value: "CASE_STUDY", label: "Case Study", description: "Structured challenge and result view." },
];

function createMediaFieldState(params: {
  kind: "IMAGE";
  assetId?: string | null;
  url?: string | null;
  label?: string | null;
}): MediaFieldState {
  return {
    mode: params.assetId ? "library" : "upload",
    assetId: params.assetId ?? "",
    url: params.url ?? "",
    label: params.label ?? "",
    kind: params.kind,
  };
}

function createInitialState(
  project: PortfolioProjectView | null | undefined,
  categories: PortfolioCategoryView[],
): ProjectFormState {
  return {
    categoryId: project?.category.id ?? categories[0]?.id ?? "",
    slug: project?.slug ?? "",
    clientName: project?.clientName ?? "",
    projectYear: String(project?.projectYear ?? new Date().getFullYear()),
    previewUrl: project?.previewUrl ?? "",
    sortOrder: String(project?.sortOrder ?? 0),
    viewMode: project?.viewMode ?? "GRID",
    isFeatured: project?.isFeatured ?? false,
    isPublished: project?.isPublished ?? false,
    titleAr: project?.title.ar ?? "",
    titleEn: project?.title.en ?? "",
    titleDe: project?.title.de ?? "",
    serviceLabelAr: project?.serviceLabel.ar ?? "",
    serviceLabelEn: project?.serviceLabel.en ?? "",
    serviceLabelDe: project?.serviceLabel.de ?? "",
    summaryAr: project?.summary.ar ?? "",
    summaryEn: project?.summary.en ?? "",
    summaryDe: project?.summary.de ?? "",
  };
}

function createEmptySection(index: number): SectionFormValue {
  return {
    type: "RICH_TEXT",
    titleAr: "",
    titleEn: "",
    titleDe: "",
    bodyAr: "",
    bodyEn: "",
    bodyDe: "",
    imagePath: "",
    media: createMediaFieldState({ kind: "IMAGE" }),
    linkUrl: "",
    sortOrder: index,
  };
}

function createEmptyAsset(index: number): AssetFormValue {
  return {
    kind: "IMAGE",
    filePath: "",
    fileFieldName: `asset-upload-${index}`,
    media: createMediaFieldState({ kind: "IMAGE" }),
    altAr: "",
    altEn: "",
    altDe: "",
    sortOrder: index,
  };
}

function hasText(value: string) {
  return value.trim().length > 0;
}

function sectionReady(section: SectionFormValue) {
  if (!hasText(section.titleAr) || !hasText(section.titleEn) || !hasText(section.titleDe)) {
    return false;
  }

  if (section.type === "GALLERY") {
    return hasText(section.media.assetId);
  }

  if (section.type === "LINK") {
    return hasText(section.linkUrl);
  }

  return hasText(section.bodyAr) && hasText(section.bodyEn) && hasText(section.bodyDe);
}

function assetReady(asset: AssetFormValue) {
  return hasText(asset.media.assetId) && hasText(asset.altAr) && hasText(asset.altEn) && hasText(asset.altDe);
}

function LocaleInputs({
  title,
  namePrefix,
  values,
  onChange,
  multiline = false,
}: {
  title: string;
  namePrefix?: string;
  values: { Ar: string; En: string; De: string };
  onChange: (key: "Ar" | "En" | "De", value: string) => void;
  multiline?: boolean;
}) {
  return (
    <div className="space-y-3">
      <p className="text-sm font-medium text-foreground">{title}</p>
      <div className="grid gap-3 xl:grid-cols-3">
        {locales.map((locale) => (
          <AppCard key={`${title}-${locale.suffix}`} level={2} padding="sm" className="space-y-2 rounded-nested">
            <p className="text-xs uppercase tracking-[0.18em] text-muted-foreground">{locale.label}</p>
            {multiline ? (
              <Textarea
                name={namePrefix ? `${namePrefix}${locale.suffix}` : undefined}
                rows={5}
                value={values[locale.suffix]}
                onChange={(event) => onChange(locale.suffix, event.target.value)}
              />
            ) : (
              <Input
                name={namePrefix ? `${namePrefix}${locale.suffix}` : undefined}
                value={values[locale.suffix]}
                onChange={(event) => onChange(locale.suffix, event.target.value)}
              />
            )}
          </AppCard>
        ))}
      </div>
    </div>
  );
}

function SectionHeader({
  title,
  description,
  action,
}: {
  title: string;
  description: string;
  action?: ReactNode;
}) {
  return (
    <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
      <div className="space-y-1">
        <h3 className="text-lg font-semibold text-foreground">{title}</h3>
        <p className="text-sm text-muted-foreground">{description}</p>
      </div>
      {action}
    </div>
  );
}

export function PortfolioProjectForm({
  action,
  categories,
  mediaOptions,
  project,
  formId,
  redirectPath,
}: PortfolioProjectFormProps) {
  const [projectState, setProjectState] = useState<ProjectFormState>(createInitialState(project, categories));
  const [coverMedia, setCoverMedia] = useState<MediaFieldState>(
    createMediaFieldState({
      kind: "IMAGE",
      assetId: project?.coverMediaAssetId,
      url: project?.coverImagePath,
      label: project?.title.de ?? project?.title.en ?? project?.title.ar ?? "",
    }),
  );
  const [sections, setSections] = useState<SectionFormValue[]>(
    project?.sections.length
      ? project.sections.map((section, index) => ({
          id: section.id,
          type: section.type,
          titleAr: section.title.ar,
          titleEn: section.title.en,
          titleDe: section.title.de,
          bodyAr: section.body.ar,
          bodyEn: section.body.en,
          bodyDe: section.body.de,
          imagePath: section.imagePath ?? "",
          media: createMediaFieldState({
            kind: "IMAGE",
            assetId: section.mediaAssetId,
            url: section.imagePath,
            label: section.title.de || section.title.en || section.title.ar,
          }),
          linkUrl: section.linkUrl ?? "",
          sortOrder: index,
        }))
      : [createEmptySection(0)],
  );
  const [assets, setAssets] = useState<AssetFormValue[]>(
    project?.assets.length
      ? project.assets.map((asset, index) => ({
          id: asset.id,
          kind: "IMAGE",
          filePath: asset.filePath,
          fileFieldName: `asset-upload-${index}`,
          media: createMediaFieldState({
            kind: "IMAGE",
            assetId: asset.mediaAssetId,
            url: asset.filePath,
            label: asset.alt.de || asset.alt.en || asset.alt.ar,
          }),
          altAr: asset.alt.ar,
          altEn: asset.alt.en,
          altDe: asset.alt.de,
          sortOrder: index,
        }))
      : [createEmptyAsset(0)],
  );
  const sectionsInputRef = useRef<HTMLInputElement | null>(null);
  const assetsInputRef = useRef<HTMLInputElement | null>(null);

  const sectionsPayload = JSON.stringify(sections.map((section, index) => ({ ...section, sortOrder: index })));
  const assetsPayload = JSON.stringify(assets.map((asset, index) => ({ ...asset, sortOrder: index })));

  useEffect(() => {
    sectionsInputRef.current?.dispatchEvent(new Event("input", { bubbles: true }));
    sectionsInputRef.current?.dispatchEvent(new Event("change", { bubbles: true }));
  }, [sectionsPayload]);

  useEffect(() => {
    assetsInputRef.current?.dispatchEvent(new Event("input", { bubbles: true }));
    assetsInputRef.current?.dispatchEvent(new Event("change", { bubbles: true }));
  }, [assetsPayload]);

  return (
    <form id={formId} action={action} className="space-y-10">
      <input type="hidden" name="id" value={project?.id ?? ""} />
      <input type="hidden" name="redirectPath" value={redirectPath} />
      <input type="hidden" name="currentCoverImagePath" value={project?.coverImagePath ?? ""} />
      <input type="hidden" name="viewMode" value={projectState.viewMode} />
      <input ref={sectionsInputRef} type="hidden" name="sections" value={sectionsPayload} />
      <input ref={assetsInputRef} type="hidden" name="assets" value={assetsPayload} />

      <section className="space-y-5">
        <SectionHeader
          title="Basic Information"
          description="Core data, visibility, and chosen project view."
        />

        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          <div className="space-y-2">
            <Label htmlFor="categoryId">Category</Label>
            <div className="relative">
              <FolderTree className="pointer-events-none absolute left-3 top-1/2 z-10 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Select
                name="categoryId"
                value={projectState.categoryId}
                onValueChange={(value) => setProjectState((current) => ({ ...current, categoryId: value }))}
              >
                <SelectTrigger id="categoryId" className="pl-9">
                  <SelectValue placeholder="Category" />
                </SelectTrigger>
                <SelectContent>
                  {categories.map((category) => (
                    <SelectItem key={category.id} value={category.id}>
                      {category.name.de} / {category.name.en}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="slug">Slug</Label>
            <div className="relative">
              <Text className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input id="slug" name="slug" value={projectState.slug} onChange={(event) => setProjectState((current) => ({ ...current, slug: event.target.value }))} className="pl-9" />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="clientName">Client</Label>
            <div className="relative">
              <UserRound className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input id="clientName" name="clientName" value={projectState.clientName} onChange={(event) => setProjectState((current) => ({ ...current, clientName: event.target.value }))} className="pl-9" />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="projectYear">Year</Label>
            <div className="relative">
              <CalendarDays className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input id="projectYear" name="projectYear" type="number" min="2000" max="2100" value={projectState.projectYear} onChange={(event) => setProjectState((current) => ({ ...current, projectYear: event.target.value }))} className="pl-9" />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="previewUrl">Preview URL</Label>
            <div className="relative">
              <Link2 className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input id="previewUrl" name="previewUrl" value={projectState.previewUrl} onChange={(event) => setProjectState((current) => ({ ...current, previewUrl: event.target.value }))} className="pl-9" />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="sortOrder">Sort Order</Label>
            <div className="relative">
              <Layers3 className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input id="sortOrder" name="sortOrder" type="number" min="0" value={projectState.sortOrder} onChange={(event) => setProjectState((current) => ({ ...current, sortOrder: event.target.value }))} className="pl-9" />
            </div>
          </div>
        </div>

        <div className="grid gap-3 xl:grid-cols-3">
          {viewModeOptions.map((option) => (
            <button
              key={option.value}
              type="button"
              onClick={() => setProjectState((current) => ({ ...current, viewMode: option.value }))}
              className={cn(
                "rounded-surface border px-4 py-4 text-left transition-colors",
                projectState.viewMode === option.value
                  ? "border-input bg-accent/20"
                  : "border-border/70 bg-background hover:border-input hover:bg-accent/10",
              )}
            >
              <p className="text-sm font-semibold text-foreground">{option.label}</p>
              <p className="mt-1 text-sm text-muted-foreground">{option.description}</p>
            </button>
          ))}
        </div>

        <div className="grid gap-3 md:grid-cols-2">
          <label className="flex items-center justify-between rounded-nested border border-input bg-card px-4 py-3">
            <div>
              <p className="text-sm font-medium text-foreground">Featured</p>
            </div>
            <input type="checkbox" name="isFeatured" checked={projectState.isFeatured} onChange={(event) => setProjectState((current) => ({ ...current, isFeatured: event.target.checked }))} />
          </label>
          <label className="flex items-center justify-between rounded-nested border border-input bg-card px-4 py-3">
            <div>
              <p className="text-sm font-medium text-foreground">Published</p>
            </div>
            <input type="checkbox" name="isPublished" checked={projectState.isPublished} onChange={(event) => setProjectState((current) => ({ ...current, isPublished: event.target.checked }))} />
          </label>
        </div>
      </section>

      <section className="space-y-5">
        <SectionHeader
          title="Localized Content"
          description="Project title, service label, and summary in all locales."
        />

        <LocaleInputs
          title="Project Title"
          namePrefix="title"
          values={{ Ar: projectState.titleAr, En: projectState.titleEn, De: projectState.titleDe }}
          onChange={(key, value) => setProjectState((current) => ({ ...current, [`title${key}`]: value }))}
        />

        <LocaleInputs
          title="Service Label"
          namePrefix="serviceLabel"
          values={{ Ar: projectState.serviceLabelAr, En: projectState.serviceLabelEn, De: projectState.serviceLabelDe }}
          onChange={(key, value) => setProjectState((current) => ({ ...current, [`serviceLabel${key}`]: value }))}
        />

        <LocaleInputs
          title="Summary"
          namePrefix="summary"
          values={{ Ar: projectState.summaryAr, En: projectState.summaryEn, De: projectState.summaryDe }}
          onChange={(key, value) => setProjectState((current) => ({ ...current, [`summary${key}`]: value }))}
          multiline
        />
      </section>

      <section className="space-y-5">
        <SectionHeader
          title="Cover Media"
          description="Select the cover only from media library."
        />

        <MediaFieldPicker
          title="Cover"
          value={coverMedia}
          onChange={setCoverMedia}
          options={mediaOptions}
          hasInitialValue={Boolean(project?.coverImagePath || project?.coverMediaAssetId)}
          inputName="coverMedia"
          fileFieldName="coverFile"
          allowClear
          clearLabel="Remove Cover"
          emptyValue={{ mode: "upload", assetId: "", url: "", label: "" }}
        />
      </section>

      <section className="space-y-5">
        <SectionHeader
          title="Sections"
          description="Every section stays inline and simple."
          action={(
            <Button type="button" variant="outline" onClick={() => setSections((current) => [...current, createEmptySection(current.length)])}>
              <Plus className="h-4 w-4" />
              Add Section
            </Button>
          )}
        />

        <div className="space-y-4">
          {sections.map((section, index) => (
            <div key={section.id ?? `section-${index}`} className="space-y-4 rounded-surface border border-border/70 bg-background p-4">
              <div className="flex flex-wrap items-center justify-between gap-3">
                <div className="flex items-center gap-3">
                  <Badge variant={sectionReady(section) ? "success" : "outline"}>
                    {sectionReady(section) ? "Ready" : "Open"}
                  </Badge>
                  <p className="text-sm font-medium text-foreground">{`Section ${index + 1}`}</p>
                </div>
                <div className="flex gap-2">
                  <Button type="button" variant="outline" onClick={() => setSections((current) => moveArrayItem(current, index, index - 1))} disabled={index === 0}>
                    <ArrowUp className="h-4 w-4" />
                  </Button>
                  <Button type="button" variant="outline" onClick={() => setSections((current) => moveArrayItem(current, index, index + 1))} disabled={index === sections.length - 1}>
                    <ArrowDown className="h-4 w-4" />
                  </Button>
                  <Button type="button" variant="ghost" className="text-destructive" onClick={() => sections.length > 1 && setSections((current) => current.filter((_, currentIndex) => currentIndex !== index))} disabled={sections.length === 1}>
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </div>
              </div>

              <div className="grid gap-4 md:grid-cols-2">
                <div className="space-y-2">
                  <Label>Type</Label>
                  <Select value={section.type} onValueChange={(value) => setSections((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, type: value as PortfolioSectionType } : item))}>
                    <SelectTrigger>
                      <SelectValue placeholder="Type" />
                    </SelectTrigger>
                    <SelectContent>
                      {sectionTypeOptions.map((type) => (
                        <SelectItem key={type} value={type}>{type}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {section.type === "LINK" ? (
                  <div className="space-y-2">
                    <Label>Link URL</Label>
                    <Input value={section.linkUrl} onChange={(event) => setSections((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, linkUrl: event.target.value } : item))} />
                  </div>
                ) : null}
              </div>

              {section.type === "GALLERY" ? (
                <MediaFieldPicker
                  title="Section Image"
                  value={section.media}
                  onChange={(media) => setSections((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, media, imagePath: media.url } : item))}
                  options={mediaOptions}
                  hasInitialValue={Boolean(section.media.assetId || section.imagePath)}
                  inputName={`section-media-${index}`}
                  fileFieldName={`section-image-upload-${index}`}
                  allowClear
                  clearLabel="Remove Image"
                  emptyValue={{ mode: "upload", assetId: "", url: "", label: "" }}
                />
              ) : null}

              <LocaleInputs
                title="Section Title"
                values={{ Ar: section.titleAr, En: section.titleEn, De: section.titleDe }}
                onChange={(key, value) => setSections((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, [`title${key}`]: value } : item))}
              />

              {section.type !== "GALLERY" && section.type !== "LINK" ? (
                <LocaleInputs
                  title="Section Body"
                  values={{ Ar: section.bodyAr, En: section.bodyEn, De: section.bodyDe }}
                  onChange={(key, value) => setSections((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, [`body${key}`]: value } : item))}
                  multiline
                />
              ) : null}
            </div>
          ))}
        </div>
      </section>

      <section className="space-y-5">
        <SectionHeader
          title="Assets"
          description="Images from media library only."
          action={(
            <Button type="button" variant="outline" onClick={() => setAssets((current) => [...current, createEmptyAsset(current.length)])}>
              <Plus className="h-4 w-4" />
              Add Asset
            </Button>
          )}
        />

        <div className="space-y-4">
          {assets.map((asset, index) => (
            <div key={asset.id ?? `asset-${index}`} className="space-y-4 rounded-surface border border-border/70 bg-background p-4">
              <div className="flex flex-wrap items-center justify-between gap-3">
                <div className="flex items-center gap-3">
                  <Badge variant={assetReady(asset) ? "success" : "outline"}>
                    {assetReady(asset) ? "Ready" : "Open"}
                  </Badge>
                  <p className="text-sm font-medium text-foreground">{`Asset ${index + 1}`}</p>
                </div>
                <div className="flex gap-2">
                  <Button type="button" variant="outline" onClick={() => setAssets((current) => moveArrayItem(current, index, index - 1))} disabled={index === 0}>
                    <ArrowUp className="h-4 w-4" />
                  </Button>
                  <Button type="button" variant="outline" onClick={() => setAssets((current) => moveArrayItem(current, index, index + 1))} disabled={index === assets.length - 1}>
                    <ArrowDown className="h-4 w-4" />
                  </Button>
                  <Button type="button" variant="ghost" className="text-destructive" onClick={() => assets.length > 1 && setAssets((current) => current.filter((_, currentIndex) => currentIndex !== index))} disabled={assets.length === 1}>
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </div>
              </div>

              <MediaFieldPicker
                title="Asset Image"
                value={asset.media}
                onChange={(media) => setAssets((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, media, filePath: media.url } : item))}
                options={mediaOptions}
                hasInitialValue={Boolean(asset.media.assetId || asset.filePath)}
                inputName={`asset-media-${index}`}
                fileFieldName={asset.fileFieldName}
                allowClear
                clearLabel="Remove Asset"
                emptyValue={{ mode: "upload", assetId: "", url: "", label: "" }}
              />

              <LocaleInputs
                title="Alt Text"
                values={{ Ar: asset.altAr, En: asset.altEn, De: asset.altDe }}
                onChange={(key, value) => setAssets((current) => current.map((item, currentIndex) => currentIndex === index ? { ...item, [`alt${key}`]: value } : item))}
              />
            </div>
          ))}
        </div>
      </section>

      <div className="flex justify-end">
        <Button type="submit">
          Save Project
        </Button>
      </div>
    </form>
  );
}
