"use client";

import type { MediaKind, PortfolioAssetKind, PortfolioSectionType } from "@prisma/client";
import { ArrowDown, ArrowUp, Plus, Trash2 } from "lucide-react";
import { useState } from "react";

import { MediaFieldPicker, type MediaFieldState } from "@/components/root/media-field-picker";
import { AppCard } from "@/components/ui/app-card";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import { moveArrayItem } from "@/lib/array";
import type { MediaOption } from "@/lib/media";
import type { PortfolioCategoryView, PortfolioProjectView } from "@/lib/portfolio";

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: PortfolioAssetKind;
  filePath: string;
  fileFieldName: string;
  media: MediaFieldState;
  altAr: string;
  altEn: string;
  altDe: string;
  sortOrder: number;
};

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

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

const assetKindOptions: PortfolioAssetKind[] = ["IMAGE", "DOCUMENT"];
const localeFieldConfig = [
  { key: "ar" as const, suffix: "Ar" as const, label: "AR" },
  { key: "en" as const, suffix: "En" as const, label: "EN" },
  { key: "de" as const, suffix: "De" as const, label: "DE" },
];

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

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,
  };
}

export function PortfolioProjectForm({
  action,
  categories,
  mediaOptions,
  project,
  redirectPath,
  submitLabel,
}: PortfolioProjectFormProps) {
  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: asset.kind,
          filePath: asset.filePath,
          fileFieldName: `asset-upload-${index}`,
          media: createMediaFieldState({
            kind: asset.kind,
            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,
        }))
      : [],
  );

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

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

  return (
    <form action={action} className="space-y-6">
      <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="sections" value={sectionsPayload} />
      <input type="hidden" name="assets" value={assetsPayload} />

      <AppCard>
        <CardHeader>
          <CardTitle>Project Basics</CardTitle>
        </CardHeader>
        <CardContent className="grid gap-4 md:grid-cols-2">
          <div className="space-y-2">
            <Label htmlFor="categoryId">Category</Label>
            <select
              id="categoryId"
              name="categoryId"
              defaultValue={project?.category.id ?? categories[0]?.id ?? ""}
              className="flex h-11 w-full rounded-pill border border-border bg-background px-4 text-sm text-foreground shadow-sm"
              required
            >
              {categories.map((category) => (
                <option key={category.id} value={category.id}>
                  {category.name.de} / {category.name.en}
                </option>
              ))}
            </select>
          </div>

          <div className="space-y-2">
            <Label htmlFor="slug">Slug</Label>
            <Input id="slug" name="slug" defaultValue={project?.slug ?? ""} required />
          </div>

          <div className="space-y-2">
            <Label htmlFor="clientName">Client Name</Label>
            <Input
              id="clientName"
              name="clientName"
              defaultValue={project?.clientName ?? ""}
              required
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="projectYear">Project Year</Label>
            <Input
              id="projectYear"
              name="projectYear"
              type="number"
              min="2000"
              max="2100"
              defaultValue={project?.projectYear ?? new Date().getFullYear()}
              required
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="previewUrl">Preview URL</Label>
            <Input
              id="previewUrl"
              name="previewUrl"
              type="url"
              defaultValue={project?.previewUrl ?? ""}
              placeholder="https://example.com"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="sortOrder">Sort Order</Label>
            <Input
              id="sortOrder"
              name="sortOrder"
              type="number"
              min="0"
              defaultValue={project?.sortOrder ?? 0}
              required
            />
          </div>

          <div className="space-y-2 md:col-span-2">
            <MediaFieldPicker
              title="Cover Image"
              value={coverMedia}
              onChange={setCoverMedia}
              options={mediaOptions}
              inputName="coverMedia"
              fileFieldName="coverFile"
              accept="image/*,.svg"
            />
          </div>

          <label className="flex items-center gap-3 rounded-nested border border-border px-4 py-3 text-sm">
            <input type="checkbox" name="isFeatured" defaultChecked={project?.isFeatured ?? false} />
            Featured
          </label>

          <label className="flex items-center gap-3 rounded-nested border border-border px-4 py-3 text-sm">
            <input type="checkbox" name="isPublished" defaultChecked={project?.isPublished ?? false} />
            Published
          </label>
        </CardContent>
      </AppCard>

      <AppCard>
        <CardHeader>
          <CardTitle>Localized Content</CardTitle>
        </CardHeader>
        <CardContent>
          <Tabs defaultValue="de">
            <TabsList>
              {localeFieldConfig.map((locale) => (
                <TabsTrigger key={locale.key} value={locale.key}>
                  {locale.label}
                </TabsTrigger>
              ))}
            </TabsList>
            {localeFieldConfig.map((locale) => (
              <TabsContent key={locale.key} value={locale.key}>
                <div className="grid gap-4 rounded-surface border border-border p-4 md:grid-cols-2">
                  <div className="md:col-span-2 text-sm text-muted-foreground">
                    {locale.key === "ar"
                      ? "Arabic content for the Arabic website."
                      : locale.key === "en"
                        ? "English content for the English website."
                        : "German content for the German website."}
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor={`title${locale.suffix}`}>{`Title ${locale.label}`}</Label>
                    <Input
                      id={`title${locale.suffix}`}
                      name={`title${locale.suffix}`}
                      defaultValue={project?.title[locale.key] ?? ""}
                      required
                    />
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor={`serviceLabel${locale.suffix}`}>{`Service Label ${locale.label}`}</Label>
                    <Input
                      id={`serviceLabel${locale.suffix}`}
                      name={`serviceLabel${locale.suffix}`}
                      defaultValue={project?.serviceLabel[locale.key] ?? ""}
                      required
                    />
                  </div>
                  <div className="space-y-2 md:col-span-2">
                    <Label htmlFor={`summary${locale.suffix}`}>{`Summary ${locale.label}`}</Label>
                    <Textarea
                      id={`summary${locale.suffix}`}
                      name={`summary${locale.suffix}`}
                      defaultValue={project?.summary[locale.key] ?? ""}
                      rows={4}
                      required
                    />
                  </div>
                </div>
              </TabsContent>
            ))}
          </Tabs>
        </CardContent>
      </AppCard>

      <AppCard>
        <CardHeader className="flex flex-row items-center justify-between">
          <CardTitle>Sections</CardTitle>
          <Button
            type="button"
            variant="outline"
            onClick={() => setSections((current) => [...current, createEmptySection(current.length)])}
          >
            <Plus className="h-4 w-4" />
            Add Section
          </Button>
        </CardHeader>
        <CardContent className="space-y-4">
          {sections.map((section, index) => (
            <AppCard key={section.id ?? `${section.type}-${index}`} level={2}>
              <CardContent className="space-y-4 p-4">
                <div className="flex items-center justify-between gap-4">
                  <p className="text-sm font-medium text-foreground">Section #{index + 1}</p>
                  <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={() =>
                        setSections((current) => current.filter((_, currentIndex) => currentIndex !== index))
                      }
                      disabled={sections.length === 1}
                    >
                      <Trash2 className="h-4 w-4" />
                      Remove
                    </Button>
                  </div>
                </div>

                <div className="grid gap-4 md:grid-cols-2">
                  <div className="space-y-2">
                    <Label>Type</Label>
                    <select
                      value={section.type}
                      onChange={(event) =>
                        setSections((current) =>
                          current.map((item, currentIndex) =>
                            currentIndex === index
                              ? { ...item, type: event.target.value as PortfolioSectionType }
                              : item,
                          ),
                        )
                      }
                      className="flex h-11 w-full rounded-pill border border-border bg-background px-4 text-sm text-foreground shadow-sm"
                    >
                      {sectionTypeOptions.map((type) => (
                        <option key={type} value={type}>
                          {type}
                        </option>
                      ))}
                    </select>
                  </div>

                  <div className="space-y-2 md:col-span-2">
                    <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}
                      inputName={`section-media-${index}`}
                      fileFieldName={`section-image-upload-${index}`}
                      accept="image/*,.svg"
                    />
                  </div>

                  <div className="space-y-2 md:col-span-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>

                  {localeFieldConfig.map((locale) => (
                    <div key={`${locale.key}-title-${index}`} className="space-y-2">
                      <Label>{`Title ${locale.label}`}</Label>
                      <Input
                        value={section[`title${locale.suffix}` as keyof SectionFormValue] as string}
                        onChange={(event) =>
                          setSections((current) =>
                            current.map((item, currentIndex) =>
                              currentIndex === index
                                ? {
                                    ...item,
                                    [`title${locale.suffix}`]: event.target.value,
                                  }
                                : item,
                            ),
                          )
                        }
                      />
                    </div>
                  ))}

                  {localeFieldConfig.map((locale) => (
                    <div key={`${locale.key}-body-${index}`} className="space-y-2 md:col-span-2">
                      <Label>{`Body ${locale.label}`}</Label>
                      <Textarea
                        rows={4}
                        value={section[`body${locale.suffix}` as keyof SectionFormValue] as string}
                        onChange={(event) =>
                          setSections((current) =>
                            current.map((item, currentIndex) =>
                              currentIndex === index
                                ? {
                                    ...item,
                                    [`body${locale.suffix}`]: event.target.value,
                                  }
                                : item,
                            ),
                          )
                        }
                      />
                    </div>
                  ))}
                </div>
              </CardContent>
            </AppCard>
          ))}
        </CardContent>
      </AppCard>

      <AppCard>
        <CardHeader className="flex flex-row items-center justify-between">
          <CardTitle>Assets</CardTitle>
          <Button
            type="button"
            variant="outline"
            onClick={() => setAssets((current) => [...current, createEmptyAsset(current.length)])}
          >
            <Plus className="h-4 w-4" />
            Add Asset
          </Button>
        </CardHeader>
        <CardContent className="space-y-4">
          {assets.length === 0 ? (
            <p className="text-sm text-muted-foreground">No assets added yet.</p>
          ) : null}

          {assets.map((asset, index) => (
            <AppCard key={asset.id ?? `${asset.kind}-${index}`} level={2}>
              <CardContent className="space-y-4 p-4">
                <div className="flex items-center justify-between gap-4">
                  <p className="text-sm font-medium text-foreground">Asset #{index + 1}</p>
                  <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={() =>
                        setAssets((current) => current.filter((_, currentIndex) => currentIndex !== index))
                      }
                    >
                      <Trash2 className="h-4 w-4" />
                      Remove
                    </Button>
                  </div>
                </div>

                <div className="grid gap-4 md:grid-cols-2">
                  <div className="space-y-2">
                    <Label>Kind</Label>
                    <select
                      value={asset.kind}
                      onChange={(event) =>
                        setAssets((current) =>
                          current.map((item, currentIndex) =>
                            currentIndex === index
                              ? {
                                  ...item,
                                  kind: event.target.value as PortfolioAssetKind,
                                  media: {
                                    ...item.media,
                                    kind: event.target.value as PortfolioAssetKind,
                                  },
                                }
                              : item,
                          ),
                        )
                      }
                      className="flex h-11 w-full rounded-pill border border-border bg-background px-4 text-sm text-foreground shadow-sm"
                    >
                      {assetKindOptions.map((kind) => (
                        <option key={kind} value={kind}>
                          {kind}
                        </option>
                      ))}
                    </select>
                  </div>

                  <div className="space-y-2 md:col-span-2">
                    <MediaFieldPicker
                      title="Asset File"
                      value={asset.media}
                      onChange={(media) =>
                        setAssets((current) =>
                          current.map((item, currentIndex) =>
                            currentIndex === index
                              ? {
                                  ...item,
                                  media,
                                  filePath: media.url,
                                }
                              : item,
                          ),
                        )
                      }
                      options={mediaOptions}
                      inputName={`asset-media-${index}`}
                      fileFieldName={asset.fileFieldName}
                      accept="image/*,.svg,.pdf"
                    />
                  </div>

                  {localeFieldConfig.map((locale) => (
                    <div key={`${locale.key}-asset-${index}`} className="space-y-2">
                      <Label>{`Alt ${locale.label}`}</Label>
                      <Input
                        value={asset[`alt${locale.suffix}` as keyof AssetFormValue] as string}
                        onChange={(event) =>
                          setAssets((current) =>
                            current.map((item, currentIndex) =>
                              currentIndex === index
                                ? {
                                    ...item,
                                    [`alt${locale.suffix}`]: event.target.value,
                                  }
                                : item,
                            ),
                          )
                        }
                      />
                    </div>
                  ))}
                </div>
              </CardContent>
            </AppCard>
          ))}
        </CardContent>
      </AppCard>

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