﻿"use client";

import Link from "next/link";
import { useCallback, useEffect, useId, useRef, useState, type FormEvent, type ReactNode } from "react";
import { toast } from "sonner";
import { Button } from "@/components/Button";
import { ApiError, profileApi, publicProfilePath, type ValidationErrors } from "@/lib/api";
import { Card } from "@/components/ui/Card";
import { EmptyState } from "@/components/ui/EmptyState";
import { ErrorState } from "@/components/ui/ErrorState";
import { fieldClassName, fieldInvalidClassName, textareaClassName } from "@/components/ui/field-styles";
import { PageHeader } from "@/components/ui/PageHeader";
import { Skeleton } from "@/components/ui/Skeleton";
import {
  BRAND_LOGO_ACCEPT,
  BRAND_LOGO_HINT,
  brandLogoButtonLabel,
  validateBrandLogoFile,
} from "@/lib/brand-logo";
import { cn } from "@/lib/cn";
import {
  CREATOR_COUNTRY_OPTIONS,
  CREATOR_GENDER_OPTIONS,
  CREATOR_NICHE_OPTIONS,
  creatorGenderLabel,
  type CreatorGenderValue,
} from "@/lib/creator-personal-info";
import type { User } from "@/types/auth";
import type { BrandProfile, CreatorProfile, Profile } from "@/types/profile";
import { DashboardShell } from "./DashboardShell";
import { ConnectedAccountChip } from "./SocialAccountUi";
import { useSocialAccounts } from "./useSocialAccounts";

const field = fieldClassName;
const textareaField = textareaClassName;
const fieldInvalid = fieldInvalidClassName;

function emptyToNull(value: string): string | null {
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : null;
}

function hasValue(value: string | null | undefined): boolean {
  return (value ?? "").trim().length > 0;
}

function firstFieldError(errors: ValidationErrors, key: string): string | undefined {
  return errors[key]?.[0];
}

function initialsFrom(value: string): string {
  const parts = value.trim().split(/\s+/).filter(Boolean);

  if (parts.length === 0) {
    return "P";
  }

  if (parts.length === 1) {
    return parts[0].slice(0, 2).toUpperCase();
  }

  return `${parts[0][0] ?? ""}${parts[1][0] ?? ""}`.toUpperCase();
}

function isDisplayableImage(value: string): boolean {
  return /^(https?:\/\/|\/|blob:)/i.test(value.trim());
}

function formMessageFromApiError(error: ApiError): string {
  if (error.status === 403) {
    return "You don’t have permission to do that.";
  }

  if (error.status === 413) {
    return "That image is too large. Please choose a smaller file.";
  }

  if (error.status === 404) {
    return "Something went wrong. Please try again.";
  }

  if (error.kind === "server") {
    return "Something went wrong. Please try again.";
  }

  if (error.kind === "rate_limited") {
    return error.message || "Too many attempts. Please wait a moment and try again.";
  }

  if (error.kind === "network") {
    return error.message || "Unable to reach the server. Check your connection and try again.";
  }

  if (error.kind === "validation") {
    return error.message || "Please check the highlighted fields and try again.";
  }

  if (error.kind === "unauthenticated") {
    return error.message || "Your session has expired. Please sign in again.";
  }

  return "Something went wrong. Please try again.";
}

function filledCount(values: Array<string | null>): { filled: number; total: number } {
  return {
    filled: values.filter((value) => (value ?? "").trim().length > 0).length,
    total: values.length,
  };
}

type ChecklistItem = {
  id: string;
  label: string;
  complete: boolean;
};

function creatorChecklist(profile: CreatorProfile): ChecklistItem[] {
  return [
    { id: "display_name", label: "Display name", complete: hasValue(profile.display_name) },
    { id: "username", label: "Username", complete: hasValue(profile.username) },
    { id: "profile_image", label: "Profile photo", complete: hasValue(profile.profile_image) },
    { id: "bio", label: "Bio", complete: hasValue(profile.bio) },
    { id: "country", label: "Country", complete: hasValue(profile.country) },
    { id: "niche", label: "Niche", complete: hasValue(profile.niche) },
  ];
}

function FieldError({ id, message }: { id: string; message?: string }) {
  if (!message) {
    return null;
  }

  return (
    <p id={id} className="mt-1.5 break-words text-[0.8rem] text-accent">
      {message}
    </p>
  );
}

function FormSection({
  title,
  children,
}: {
  title: string;
  children: ReactNode;
}) {
  return (
    <section className="border-t border-line pt-4 first:border-t-0 first:pt-0">
      <h2 className="text-[0.875rem] font-semibold text-primary">{title}</h2>
      <div className="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">{children}</div>
    </section>
  );
}

function TextField({
  id,
  label,
  value,
  onChange,
  error,
  type = "text",
  disabled,
  autoComplete,
  hint,
  span = false,
}: {
  id: string;
  label: string;
  value: string;
  onChange: (value: string) => void;
  error?: string;
  type?: "text" | "url" | "date";
  disabled?: boolean;
  autoComplete?: string;
  hint?: string;
  span?: boolean;
}) {
  const errorId = `${id}-error`;
  const hintId = `${id}-hint`;

  return (
    <div className={span ? "sm:col-span-2" : undefined}>
      <label htmlFor={id} className="mb-1 block text-[0.8125rem] font-medium text-ink-60">
        {label}
      </label>
      <input
        id={id}
        type={type}
        value={value}
        autoComplete={autoComplete}
        disabled={disabled}
        aria-invalid={error ? true : undefined}
        aria-describedby={[hint ? hintId : null, error ? errorId : null].filter(Boolean).join(" ") || undefined}
        className={cn(field, error && fieldInvalid)}
        onChange={(event) => onChange(event.target.value)}
      />
      {hint ? (
        <p id={hintId} className="mt-1.5 text-[0.78rem] text-ink-40">
          {hint}
        </p>
      ) : null}
      <FieldError id={errorId} message={error} />
    </div>
  );
}

function SelectField({
  id,
  label,
  value,
  onChange,
  error,
  disabled,
  hint,
  span = false,
  options,
  placeholder = "Select…",
}: {
  id: string;
  label: string;
  value: string;
  onChange: (value: string) => void;
  error?: string;
  disabled?: boolean;
  hint?: string;
  span?: boolean;
  options: { value: string; label: string }[];
  placeholder?: string;
}) {
  const errorId = `${id}-error`;
  const hintId = `${id}-hint`;

  return (
    <div className={span ? "sm:col-span-2" : undefined}>
      <label htmlFor={id} className="mb-1 block text-[0.8125rem] font-medium text-ink-60">
        {label}
      </label>
      <select
        id={id}
        value={value}
        disabled={disabled}
        aria-invalid={error ? true : undefined}
        aria-describedby={[hint ? hintId : null, error ? errorId : null].filter(Boolean).join(" ") || undefined}
        className={cn(field, error && fieldInvalid)}
        onChange={(event) => onChange(event.target.value)}
      >
        <option value="">{placeholder}</option>
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
      {hint ? (
        <p id={hintId} className="mt-1.5 text-[0.78rem] text-ink-40">
          {hint}
        </p>
      ) : null}
      <FieldError id={errorId} message={error} />
    </div>
  );
}

function TextAreaField({
  id,
  label,
  value,
  onChange,
  error,
  disabled,
}: {
  id: string;
  label: string;
  value: string;
  onChange: (value: string) => void;
  error?: string;
  disabled?: boolean;
}) {
  const errorId = `${id}-error`;

  return (
    <div className="sm:col-span-2">
      <label htmlFor={id} className="mb-1 block text-[0.8125rem] font-medium text-ink-60">
        {label}
      </label>
      <textarea
        id={id}
        value={value}
        rows={4}
        disabled={disabled}
        aria-invalid={error ? true : undefined}
        aria-describedby={error ? errorId : undefined}
        className={cn(textareaField, error && fieldInvalid)}
        onChange={(event) => onChange(event.target.value)}
      />
      <FieldError id={errorId} message={error} />
    </div>
  );
}

function AvatarPreview({
  src,
  initials,
  alt,
  sizeClassName = "size-16 text-[0.95rem]",
}: {
  src: string;
  initials: string;
  alt: string;
  sizeClassName?: string;
}) {
  const [failed, setFailed] = useState(false);
  const showImage = Boolean(src) && isDisplayableImage(src) && !failed;

  useEffect(() => {
    setFailed(false);
  }, [src]);

  return (
    <span
      className={cn(
        "inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary font-semibold tracking-wide text-white",
        sizeClassName,
      )}
      role={showImage ? undefined : "img"}
      aria-label={showImage ? undefined : alt}
      aria-hidden={showImage ? true : undefined}
    >
      {showImage ? (
        <img src={src} alt={alt} className="size-full object-cover" onError={() => setFailed(true)} />
      ) : (
        initials
      )}
    </span>
  );
}

function IdentityCard({
  image,
  name,
  username,
  accountLabel,
}: {
  image: string;
  name: string;
  username: string;
  accountLabel: "Creator" | "Brand";
}) {
  return (
    <div className="rounded-pv border border-line bg-surface p-3">
      <div className="flex min-w-0 items-center gap-3">
        <AvatarPreview
          src={image}
          alt={name ? `Profile photo of ${name}` : `${accountLabel} profile photo`}
          initials={initialsFrom(name || accountLabel)}
          sizeClassName="size-12 text-[0.8125rem]"
        />
        <div className="min-w-0">
          <p className="truncate text-[0.875rem] font-semibold text-primary">
            {name || "Unnamed profile"}
          </p>
          <p className="truncate text-[0.8125rem] text-ink-60">{username ? `@${username}` : "No username yet"}</p>
          <p className="mt-0.5 text-[0.6875rem] font-medium uppercase tracking-wide text-ink-40">
            {accountLabel}
          </p>
        </div>
      </div>
    </div>
  );
}

function CompletionCard({ filled, total }: { filled: number; total: number }) {
  const percent = total === 0 ? 0 : Math.round((filled / total) * 100);

  return (
    <div className="rounded-pv border border-line bg-surface p-3">
      <h2 className="text-[0.8125rem] font-semibold text-primary">Profile completion</h2>
      <p className="mt-0.5 text-[0.75rem] text-ink-60">
        {filled} of {total} fields filled
      </p>
      <div className="mt-2 h-1 overflow-hidden rounded-full bg-line" aria-hidden="true">
        <div className="h-full rounded-full bg-accent transition-[width] duration-300 motion-reduce:transition-none" style={{ width: `${percent}%` }} />
      </div>
    </div>
  );
}

function ProfileSkeleton({ variant }: { variant: "creator" | "brand" }) {
  if (variant === "creator") {
    return (
      <div aria-busy="true" aria-live="polite">
        <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_16rem]">
          <div className="space-y-4">
            <Skeleton className="h-40 w-full" />
            <Skeleton className="h-28 w-full" />
            <Skeleton className="h-24 w-full" />
          </div>
          <div className="hidden space-y-3 lg:block">
            <Skeleton className="h-28 w-full" />
            <Skeleton className="h-44 w-full" />
          </div>
        </div>
        <p className="sr-only">Loading profile…</p>
      </div>
    );
  }

  return (
    <div aria-busy="true" aria-live="polite">
      <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_16rem]">
        <div className="space-y-4">
          <Skeleton className="h-32 w-full" />
          <Skeleton className="h-44 w-full" />
        </div>
        <div className="hidden space-y-3 lg:block">
          <Skeleton className="h-24 w-full" />
          <Skeleton className="h-20 w-full" />
        </div>
      </div>
      <p className="sr-only">Loading profile…</p>
    </div>
  );
}

function PlaceholderText({ children }: { children: string }) {
  return <span className="text-ink-40">{children}</span>;
}

function CreatorRatingCard() {
  return (
    <div className="rounded-pv border border-line bg-surface p-3" aria-labelledby="profile-rating-heading">
      <h2 id="profile-rating-heading" className="text-[0.8125rem] font-semibold text-primary">
        Rating
      </h2>
      <p className="mt-2 text-[0.875rem] font-medium text-primary">No ratings yet</p>
      <p className="mt-1 text-[0.75rem] text-ink-60">
        Ratings appear after brands review your work.
      </p>
    </div>
  );
}

function CreatorSocialAccountsCard() {
  const { accounts, isLoading, error, retry } = useSocialAccounts();

  return (
    <div className="rounded-pv border border-line bg-surface p-4" aria-labelledby="profile-social-heading">
      <div className="flex items-center justify-between gap-2">
        <h2 id="profile-social-heading" className="text-[0.875rem] font-semibold text-primary">
          Social accounts
        </h2>
        {!isLoading && !error ? (
          <Link
            href="/dashboard/social-accounts"
            className="shrink-0 text-[0.8125rem] font-medium text-accent hover:text-accent-hover"
          >
            Manage
          </Link>
        ) : null}
      </div>
      {isLoading ? (
        <div className="mt-3 flex flex-wrap gap-2" aria-busy="true" aria-live="polite">
          <Skeleton className="h-8 w-28 rounded-pv" />
          <Skeleton className="h-8 w-32 rounded-pv" />
          <Skeleton className="h-8 w-24 rounded-pv" />
        </div>
      ) : null}
      {!isLoading && error ? (
        <div className="mt-3">
          <ErrorState
            title="Unable to load social accounts"
            message="We couldn't load your connected accounts right now."
            onRetry={retry}
            className="border-0 bg-bg p-3 shadow-none"
          />
        </div>
      ) : null}
      {!isLoading && !error && accounts.length === 0 ? (
        <EmptyState
          className="mt-3 border-0 bg-bg py-4 shadow-none"
          title="No accounts connected"
          description="Connect social platforms to complete your profile."
          action={
            <Button href="/dashboard/social-accounts" size="sm" variant="secondary">
              Connect accounts
            </Button>
          }
        />
      ) : null}
      {!isLoading && !error && accounts.length > 0 ? (
        <ul className="mt-3 flex flex-wrap gap-2" role="list">
          {accounts.map((account) => (
            <li key={account.id}>
              <ConnectedAccountChip account={account} />
            </li>
          ))}
        </ul>
      ) : null}
    </div>
  );
}

function CreatorCompletionCard({
  checklist,
  onEdit,
}: {
  checklist: ChecklistItem[];
  onEdit: () => void;
}) {
  const filled = checklist.filter((item) => item.complete).length;
  const total = checklist.length;
  const incomplete = filled < total;

  return (
    <div className="rounded-pv border border-line bg-surface p-3" aria-labelledby="profile-completion-heading">
      <div className="flex flex-wrap items-end justify-between gap-2">
        <h2 id="profile-completion-heading" className="text-[0.8125rem] font-semibold text-primary">
          Profile checklist
        </h2>
        <p className="text-[0.75rem] text-ink-60">
          {filled} of {total}
        </p>
      </div>
      <ul className="mt-3 space-y-2">
        {checklist.map((item) => (
          <li key={item.id} className="flex min-w-0 items-center gap-2 text-[0.8125rem] text-text">
            <span
              className={cn(
                "inline-flex size-4 shrink-0 items-center justify-center rounded-full border text-[0.625rem] font-semibold",
                item.complete ? "border-primary bg-primary text-white" : "border-line bg-bg text-ink-40",
              )}
              aria-hidden="true"
            >
              {item.complete ? "✓" : ""}
            </span>
            <span>
              {item.label}
              <span className="sr-only">{item.complete ? ", complete" : ", incomplete"}</span>
            </span>
          </li>
        ))}
      </ul>
      {incomplete ? (
        <Button type="button" size="sm" className="mt-3 w-full" onClick={onEdit}>
          Complete profile
        </Button>
      ) : null}
    </div>
  );
}

function CreatorOverview({
  profile,
  onEdit,
}: {
  profile: CreatorProfile;
  onEdit: () => void;
}) {
  const checklist = creatorChecklist(profile);
  const displayName = profile.display_name?.trim() ?? "";
  const username = profile.username?.trim() ?? "";
  const bio = profile.bio?.trim() ?? "";
  const country = profile.country?.trim() ?? "";
  const niche = profile.niche?.trim() ?? "";
  const image = profile.profile_image?.trim() ?? "";
  const genderLabel = creatorGenderLabel(profile.gender, profile.gender_self_description);
  const age = profile.age;

  const ratingAndCompletion = (
    <>
      <CreatorRatingCard />
      <CreatorCompletionCard checklist={checklist} onEdit={onEdit} />
    </>
  );

  return (
    <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_16rem]">
      <div className="min-w-0 space-y-4">
        <div className="rounded-pv border border-line bg-surface p-4" aria-labelledby="profile-overview-heading">
          <div className="flex flex-col gap-4 sm:flex-row sm:items-start">
            <AvatarPreview
              src={image}
              alt={displayName ? `Profile photo of ${displayName}` : "Creator profile photo"}
              initials={initialsFrom(displayName || username || "Creator")}
              sizeClassName="size-16 text-[0.9375rem]"
            />
            <div className="min-w-0 flex-1">
              <h2 id="profile-overview-heading" className="text-[1.0625rem] font-semibold tracking-[-0.02em] text-primary">
                {displayName || <PlaceholderText>Add a display name</PlaceholderText>}
              </h2>
              <p className="mt-0.5 text-[0.8125rem] text-ink-60">
                {username ? `@${username}` : <PlaceholderText>Add a username</PlaceholderText>}
              </p>
              <dl className="mt-3 grid grid-cols-2 gap-x-4 gap-y-2">
                <div className="min-w-0">
                  <dt className="text-[0.6875rem] font-medium uppercase tracking-wide text-ink-40">Country</dt>
                  <dd className="mt-0.5 break-words text-[0.8125rem] text-text">
                    {country || <PlaceholderText>—</PlaceholderText>}
                  </dd>
                </div>
                <div className="min-w-0">
                  <dt className="text-[0.6875rem] font-medium uppercase tracking-wide text-ink-40">Niche</dt>
                  <dd className="mt-0.5 break-words text-[0.8125rem] text-text">
                    {niche || <PlaceholderText>—</PlaceholderText>}
                  </dd>
                </div>
                <div className="min-w-0">
                  <dt className="text-[0.6875rem] font-medium uppercase tracking-wide text-ink-40">Gender</dt>
                  <dd className="mt-0.5 break-words text-[0.8125rem] text-text">
                    {genderLabel || <PlaceholderText>—</PlaceholderText>}
                  </dd>
                </div>
                <div className="min-w-0">
                  <dt className="text-[0.6875rem] font-medium uppercase tracking-wide text-ink-40">Age</dt>
                  <dd className="mt-0.5 break-words text-[0.8125rem] text-text">
                    {typeof age === "number" ? age : <PlaceholderText>—</PlaceholderText>}
                  </dd>
                </div>
              </dl>
            </div>
            <div className="sm:ml-auto sm:shrink-0">
              <div className="flex flex-col gap-2 sm:items-end">
                <Button type="button" size="sm" className="w-full sm:w-auto" onClick={onEdit}>
                  Edit profile
                </Button>
                {username ? (
                  <Button
                    href={publicProfilePath(username)}
                    variant="secondary"
                    size="sm"
                    className="w-full sm:w-auto"
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    View public profile
                  </Button>
                ) : null}
              </div>
            </div>
          </div>
        </div>

        <div className="rounded-pv border border-line bg-surface p-4" aria-labelledby="profile-about-heading">
          <h2 id="profile-about-heading" className="text-[0.875rem] font-semibold text-primary">
            Bio
          </h2>
          {bio ? (
            <p className="mt-2 text-[0.8125rem] leading-relaxed break-words text-text">{bio}</p>
          ) : (
            <>
              <p className="mt-2 text-[0.8125rem] text-ink-60">Add a bio to tell brands more about you.</p>
              <Button type="button" variant="secondary" size="sm" className="mt-3" onClick={onEdit}>
                Edit profile
              </Button>
            </>
          )}
        </div>

        <CreatorSocialAccountsCard />

        <div className="space-y-3 lg:hidden">{ratingAndCompletion}</div>
      </div>
      <aside className="hidden min-w-0 space-y-3 lg:block">{ratingAndCompletion}</aside>
    </div>
  );
}

function CreatorForm({
  profile,
  disabled,
  onCancel,
  onSaved,
  onProfileUpdated,
}: {
  profile: CreatorProfile;
  disabled?: boolean;
  onCancel: () => void;
  onSaved: (profile: CreatorProfile) => void;
  onProfileUpdated: (profile: CreatorProfile) => void;
}) {
  const [displayName, setDisplayName] = useState(profile.display_name ?? "");
  const [username, setUsername] = useState(profile.username ?? "");
  const [bio, setBio] = useState(profile.bio ?? "");
  const [niche, setNiche] = useState(profile.niche ?? "");
  const [gender, setGender] = useState<CreatorGenderValue | "">(profile.gender ?? "");
  const [genderSelfDescription, setGenderSelfDescription] = useState(profile.gender_self_description ?? "");
  const [dateOfBirth, setDateOfBirth] = useState(profile.date_of_birth ?? "");
  const [country, setCountry] = useState(profile.country ?? "");
  const [photoUrl, setPhotoUrl] = useState(profile.profile_image ?? "");
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [isUploadingPhoto, setIsUploadingPhoto] = useState(false);
  const [isRemovingPhoto, setIsRemovingPhoto] = useState(false);
  const [photoError, setPhotoError] = useState("");
  const [fieldErrors, setFieldErrors] = useState<ValidationErrors>({});
  const [formError, setFormError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const formErrorId = useId();
  const photoInputId = useId();
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    return () => {
      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
      }
    };
  }, [previewUrl]);

  const busy = disabled || isSubmitting || isUploadingPhoto || isRemovingPhoto;
  const photoAlt = displayName.trim() ? `Profile photo of ${displayName.trim()}` : "Creator profile photo";

  async function handlePhotoChange(file: File | undefined) {
    if (!file || isUploadingPhoto || busy) {
      return;
    }

    setPhotoError("");

    const allowed = ["image/jpeg", "image/png", "image/webp"];

    if (!allowed.includes(file.type)) {
      setPhotoError("Use a JPEG, PNG, or WebP image.");
      return;
    }

    if (file.size > 2 * 1024 * 1024) {
      setPhotoError("That photo is too large. Please choose a smaller image.");
      return;
    }

    if (previewUrl) {
      URL.revokeObjectURL(previewUrl);
    }

    const localPreview = URL.createObjectURL(file);
    setPreviewUrl(localPreview);
    setIsUploadingPhoto(true);

    try {
      const updated = await profileApi.uploadPhoto(file);

      if (updated.account_type !== "creator") {
        throw new ApiError({ kind: "unknown" });
      }

      URL.revokeObjectURL(localPreview);
      setPreviewUrl(null);
      setPhotoUrl(updated.profile_image ?? "");
      onProfileUpdated(updated);
      toast.success("Profile photo updated.");
    } catch (error) {
      URL.revokeObjectURL(localPreview);
      setPreviewUrl(null);

      if (error instanceof ApiError) {
        if (error.isValidation) {
          setPhotoError(firstFieldError(error.errors, "photo") ?? formMessageFromApiError(error));
        } else {
          setPhotoError(formMessageFromApiError(error));
        }
      } else {
        setPhotoError("Something went wrong. Please try again.");
      }
    } finally {
      setIsUploadingPhoto(false);

      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }
  }

  async function handleRemovePhoto() {
    if (isRemovingPhoto || busy || (!photoUrl && !previewUrl)) {
      return;
    }

    setPhotoError("");
    setIsRemovingPhoto(true);

    try {
      const updated = await profileApi.deletePhoto();

      if (updated.account_type !== "creator") {
        throw new ApiError({ kind: "unknown" });
      }

      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
        setPreviewUrl(null);
      }

      setPhotoUrl("");
      onProfileUpdated(updated);
      toast.success("Profile photo removed.");
    } catch (error) {
      if (error instanceof ApiError) {
        setPhotoError(formMessageFromApiError(error));
      } else {
        setPhotoError("Something went wrong. Please try again.");
      }
    } finally {
      setIsRemovingPhoto(false);
    }
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    if (isSubmitting || disabled) {
      return;
    }

    setIsSubmitting(true);
    setFieldErrors({});
    setFormError("");

    try {
      const updated = await profileApi.update({
        username: emptyToNull(username),
        display_name: emptyToNull(displayName),
        bio: emptyToNull(bio),
        country: emptyToNull(country),
        niche: emptyToNull(niche),
        gender: gender === "" ? null : gender,
        ...(gender === "self_described"
          ? { gender_self_description: emptyToNull(genderSelfDescription) }
          : {}),
        date_of_birth: emptyToNull(dateOfBirth),
      });

      if (updated.account_type !== "creator") {
        throw new ApiError({ kind: "unknown" });
      }

      toast.success("Profile saved.");
      onSaved(updated);
    } catch (error) {
      if (error instanceof ApiError) {
        if (error.isValidation) {
          setFieldErrors(error.errors);
        }
        setFormError(formMessageFromApiError(error));
      } else {
        setFormError("Something went wrong. Please try again.");
      }
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} noValidate className="space-y-4">
      {formError ? (
        <p
          id={formErrorId}
          className="break-words rounded-pv border border-accent/30 bg-surface px-3 py-2.5 text-[0.8125rem] text-accent"
          role="alert"
        >
          {formError}
        </p>
      ) : null}
      <Card className="space-y-4">
      <FormSection title="Profile photo">
        <div className="sm:col-span-2">
          <label htmlFor={photoInputId} className="mb-3 block text-[0.82rem] font-medium text-ink-60">
            Profile photo
          </label>
          <div className="flex flex-col gap-4 sm:flex-row sm:items-center">
            <AvatarPreview
              src={previewUrl ?? photoUrl}
              alt={photoAlt}
              initials={initialsFrom(displayName || username || "Creator")}
              sizeClassName="size-20 text-[1.15rem]"
            />
            <div className="flex min-w-0 flex-1 flex-col gap-2 sm:flex-row">
              <input
                ref={fileInputRef}
                id={photoInputId}
                type="file"
                accept="image/jpeg,image/png,image/webp"
                className="sr-only"
                disabled={busy}
                onChange={(event) => void handlePhotoChange(event.target.files?.[0])}
              />
              <Button
                type="button"
                variant="secondary"
                size="sm"
                className="w-full sm:w-auto"
                disabled={busy}
                onClick={() => fileInputRef.current?.click()}
              >
                {isUploadingPhoto ? "Uploading…" : "Change photo"}
              </Button>
              {photoUrl || previewUrl ? (
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  className="w-full sm:w-auto"
                  disabled={busy}
                  onClick={() => void handleRemovePhoto()}
                >
                  {isRemovingPhoto ? "Removing…" : "Remove photo"}
                </Button>
              ) : null}
            </div>
          </div>
          <p className="mt-2 text-[0.78rem] text-ink-40">JPEG, PNG, or WebP. Maximum 2 MB.</p>
          {photoError ? (
            <p className="mt-1.5 break-words text-[0.8rem] text-accent" role="alert">
              {photoError}
            </p>
          ) : null}
        </div>
      </FormSection>
      <FormSection title="Basic information">
        <TextField
          id="display_name"
          label="Display name"
          value={displayName}
          autoComplete="name"
          disabled={busy}
          error={firstFieldError(fieldErrors, "display_name")}
          onChange={setDisplayName}
        />
        <TextField
          id="username"
          label="Username"
          value={username}
          autoComplete="username"
          disabled={busy}
          error={firstFieldError(fieldErrors, "username")}
          onChange={setUsername}
        />
        <TextAreaField
          id="bio"
          label="Bio"
          value={bio}
          disabled={busy}
          error={firstFieldError(fieldErrors, "bio")}
          onChange={setBio}
        />
        <SelectField
          id="niche"
          label="Niche"
          value={niche}
          disabled={busy}
          error={firstFieldError(fieldErrors, "niche")}
          options={CREATOR_NICHE_OPTIONS}
          placeholder="Select a niche…"
          onChange={setNiche}
        />
        <SelectField
          id="country"
          label="Country"
          value={country}
          disabled={busy}
          error={firstFieldError(fieldErrors, "country")}
          options={CREATOR_COUNTRY_OPTIONS}
          placeholder="Select a country…"
          onChange={setCountry}
        />
      </FormSection>
      <FormSection title="Personal information">
        <SelectField
          id="gender"
          label="Gender"
          value={gender}
          disabled={busy}
          error={firstFieldError(fieldErrors, "gender")}
          options={CREATOR_GENDER_OPTIONS}
          onChange={(value) => {
            setGender(value as CreatorGenderValue | "");
            if (value !== "self_described") {
              setGenderSelfDescription("");
            }
          }}
        />
        {gender === "self_described" ? (
          <TextField
            id="gender_self_description"
            label="Gender description"
            value={genderSelfDescription}
            disabled={busy}
            error={firstFieldError(fieldErrors, "gender_self_description")}
            onChange={setGenderSelfDescription}
            span
          />
        ) : null}
        <TextField
          id="date_of_birth"
          label="Date of birth"
          type="date"
          value={dateOfBirth}
          disabled={busy}
          error={firstFieldError(fieldErrors, "date_of_birth")}
          hint="Private — not shown on your public profile."
          onChange={setDateOfBirth}
        />
      </FormSection>
      </Card>
      <div className="flex flex-col gap-2 sm:flex-row">
        <Button
          type="submit"
          size="sm"
          className="w-full sm:w-auto"
          disabled={busy}
        >
          {isSubmitting ? "Saving…" : "Save changes"}
        </Button>
        <Button
          type="button"
          variant="secondary"
          size="sm"
          className="w-full sm:w-auto"
          disabled={isSubmitting || isUploadingPhoto}
          onClick={onCancel}
        >
          Cancel
        </Button>
      </div>
    </form>
  );
}

function BrandForm({
  profile,
  disabled,
}: {
  profile: BrandProfile;
  disabled?: boolean;
}) {
  const [companyName, setCompanyName] = useState(profile.company_name ?? "");
  const [username, setUsername] = useState(profile.username ?? "");
  const [description, setDescription] = useState(profile.description ?? "");
  const [website, setWebsite] = useState(profile.website ?? "");
  const [location, setLocation] = useState(profile.location ?? "");
  const [industry, setIndustry] = useState(profile.industry ?? "");
  const [logoUrl, setLogoUrl] = useState(profile.logo ?? "");
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [selectedFileName, setSelectedFileName] = useState("");
  const [isUploadingLogo, setIsUploadingLogo] = useState(false);
  const [isRemovingLogo, setIsRemovingLogo] = useState(false);
  const [logoError, setLogoError] = useState("");
  const [fieldErrors, setFieldErrors] = useState<ValidationErrors>({});
  const [formError, setFormError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [savedProfile, setSavedProfile] = useState(profile);
  const formErrorId = useId();
  const logoInputId = useId();
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    return () => {
      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
      }
    };
  }, [previewUrl]);

  const busy = disabled || isSubmitting || isUploadingLogo || isRemovingLogo;
  const hasLogo = Boolean(logoUrl || previewUrl);
  const logoAlt = companyName.trim()
    ? `Logo for ${companyName.trim()}`
    : "Brand logo";

  const completion = filledCount([
    savedProfile.company_name,
    savedProfile.username,
    savedProfile.description,
    savedProfile.website,
    savedProfile.location,
    savedProfile.industry,
    savedProfile.logo,
  ]);

  async function handleLogoChange(file: File | undefined) {
    if (!file || isUploadingLogo || busy) {
      return;
    }

    setLogoError("");

    const validation = validateBrandLogoFile(file);

    if (!validation.ok) {
      setLogoError(validation.message);
      return;
    }

    if (previewUrl) {
      URL.revokeObjectURL(previewUrl);
    }

    const localPreview = URL.createObjectURL(file);
    setPreviewUrl(localPreview);
    setSelectedFileName(file.name);
    setIsUploadingLogo(true);

    try {
      const updated = await profileApi.uploadLogo(file);

      if (updated.account_type !== "brand") {
        throw new ApiError({ kind: "unknown" });
      }

      URL.revokeObjectURL(localPreview);
      setPreviewUrl(null);
      setSelectedFileName("");
      setLogoUrl(updated.logo ?? "");
      setSavedProfile(updated);
      toast.success("Logo updated.");
    } catch (error) {
      URL.revokeObjectURL(localPreview);
      setPreviewUrl(null);
      setSelectedFileName("");

      if (error instanceof ApiError) {
        if (error.isValidation) {
          setLogoError(firstFieldError(error.errors, "logo") ?? formMessageFromApiError(error));
        } else {
          setLogoError(formMessageFromApiError(error));
        }
      } else {
        setLogoError("Something went wrong. Please try again.");
      }
    } finally {
      setIsUploadingLogo(false);

      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }
  }

  async function handleRemoveLogo() {
    if (isRemovingLogo || busy || (!logoUrl && !previewUrl)) {
      return;
    }

    setLogoError("");
    setIsRemovingLogo(true);

    try {
      const updated = await profileApi.deleteLogo();

      if (updated.account_type !== "brand") {
        throw new ApiError({ kind: "unknown" });
      }

      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
        setPreviewUrl(null);
      }

      setSelectedFileName("");
      setLogoUrl("");
      setSavedProfile(updated);
      toast.success("Logo removed.");
    } catch (error) {
      if (error instanceof ApiError) {
        setLogoError(formMessageFromApiError(error));
      } else {
        setLogoError("Something went wrong. Please try again.");
      }
    } finally {
      setIsRemovingLogo(false);
    }
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    if (isSubmitting || disabled || isUploadingLogo || isRemovingLogo) {
      return;
    }

    setIsSubmitting(true);
    setFieldErrors({});
    setFormError("");

    try {
      const updated = await profileApi.update({
        username: emptyToNull(username),
        company_name: emptyToNull(companyName),
        description: emptyToNull(description),
        website: emptyToNull(website),
        location: emptyToNull(location),
        industry: emptyToNull(industry),
      });

      if (updated.account_type !== "brand") {
        throw new ApiError({ kind: "unknown" });
      }

      setSavedProfile(updated);
      setCompanyName(updated.company_name ?? "");
      setUsername(updated.username ?? "");
      setDescription(updated.description ?? "");
      setWebsite(updated.website ?? "");
      setLocation(updated.location ?? "");
      setIndustry(updated.industry ?? "");
      setLogoUrl(updated.logo ?? "");
      toast.success("Profile saved.");
    } catch (error) {
      if (error instanceof ApiError) {
        if (error.isValidation) {
          setFieldErrors(error.errors);
        }
        setFormError(formMessageFromApiError(error));
      } else {
        setFormError("Something went wrong. Please try again.");
      }
    } finally {
      setIsSubmitting(false);
    }
  }

  const saveButton = (
    <Button type="submit" size="sm" className="w-full" disabled={busy}>
      {isSubmitting ? "Saving…" : "Save changes"}
    </Button>
  );

  return (
    <form onSubmit={handleSubmit} noValidate className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_16rem]">
      <div className="min-w-0 space-y-4">
        {formError ? (
          <p
            id={formErrorId}
            className="break-words rounded-pv border border-accent/30 bg-surface px-3 py-2.5 text-[0.8125rem] text-accent"
            role="alert"
          >
            {formError}
          </p>
        ) : null}
        <div className="lg:hidden">
          <IdentityCard
            image={previewUrl ?? logoUrl}
            name={savedProfile.company_name ?? ""}
            username={savedProfile.username ?? ""}
            accountLabel="Brand"
          />
        </div>
        <Card className="space-y-4">
        <FormSection title="Logo">
          <div className="sm:col-span-2">
            <label htmlFor={logoInputId} className="mb-3 block text-[0.82rem] font-medium text-ink-60">
              Logo
            </label>
            <div className="flex flex-col gap-4 sm:flex-row sm:items-center">
              <AvatarPreview
                src={previewUrl ?? logoUrl}
                alt={logoAlt}
                initials={initialsFrom(companyName || username || "Brand")}
                sizeClassName="size-20 text-[1.15rem]"
              />
              <div className="flex min-w-0 flex-1 flex-col gap-2 sm:flex-row">
                <input
                  ref={fileInputRef}
                  id={logoInputId}
                  type="file"
                  accept={BRAND_LOGO_ACCEPT}
                  className="sr-only"
                  disabled={busy}
                  onChange={(event) => void handleLogoChange(event.target.files?.[0])}
                />
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  className="w-full sm:w-auto"
                  disabled={busy}
                  onClick={() => fileInputRef.current?.click()}
                >
                  {brandLogoButtonLabel({ hasLogo, isUploading: isUploadingLogo })}
                </Button>
                {hasLogo ? (
                  <Button
                    type="button"
                    variant="secondary"
                    size="sm"
                    className="w-full sm:w-auto"
                    disabled={busy}
                    onClick={() => void handleRemoveLogo()}
                  >
                    {isRemovingLogo ? "Removing…" : "Remove logo"}
                  </Button>
                ) : null}
              </div>
            </div>
            {selectedFileName ? (
              <p className="mt-2 truncate text-[0.78rem] text-ink-60">{selectedFileName}</p>
            ) : null}
            <p className="mt-2 text-[0.78rem] text-ink-40">{BRAND_LOGO_HINT}</p>
            {logoError ? (
              <p className="mt-1.5 break-words text-[0.8rem] text-accent" role="alert">
                {logoError}
              </p>
            ) : null}
          </div>
        </FormSection>
        <FormSection title="Basic information">
          <TextField
            id="company_name"
            label="Company name"
            value={companyName}
            autoComplete="organization"
            disabled={busy}
            error={firstFieldError(fieldErrors, "company_name")}
            onChange={setCompanyName}
          />
          <TextField
            id="username"
            label="Username"
            value={username}
            autoComplete="username"
            disabled={busy}
            error={firstFieldError(fieldErrors, "username")}
            onChange={setUsername}
          />
          <TextAreaField
            id="description"
            label="Description"
            value={description}
            disabled={busy}
            error={firstFieldError(fieldErrors, "description")}
            onChange={setDescription}
          />
        </FormSection>
        <FormSection title="Professional information">
          <TextField
            id="website"
            label="Website"
            type="url"
            value={website}
            autoComplete="url"
            disabled={busy}
            error={firstFieldError(fieldErrors, "website")}
            onChange={setWebsite}
          />
          <TextField
            id="location"
            label="Location"
            value={location}
            disabled={busy}
            error={firstFieldError(fieldErrors, "location")}
            onChange={setLocation}
          />
          <TextField
            id="industry"
            label="Industry"
            value={industry}
            disabled={busy}
            error={firstFieldError(fieldErrors, "industry")}
            onChange={setIndustry}
          />
        </FormSection>
        </Card>
        <div className="lg:hidden">{saveButton}</div>
      </div>
      <aside className="hidden min-w-0 space-y-3 lg:block">
        <IdentityCard
          image={previewUrl ?? logoUrl}
          name={savedProfile.company_name ?? ""}
          username={savedProfile.username ?? ""}
          accountLabel="Brand"
        />
        <CompletionCard filled={completion.filled} total={completion.total} />
        {saveButton}
      </aside>
    </form>
  );
}

function emptyCreatorProfile(): CreatorProfile {
  return {
    account_type: "creator",
    username: null,
    display_name: null,
    bio: null,
    profile_image: null,
    country: null,
    niche: null,
    gender: null,
    gender_self_description: null,
    date_of_birth: null,
    age: null,
  };
}

function emptyBrandProfile(): BrandProfile {
  return {
    account_type: "brand",
    username: null,
    company_name: null,
    description: null,
    logo: null,
    website: null,
    location: null,
    industry: null,
  };
}

function CreatorProfileExperience({ profile }: { profile: CreatorProfile }) {
  const [current, setCurrent] = useState(profile);
  const [isEditing, setIsEditing] = useState(false);
  const [editKey, setEditKey] = useState(0);

  function openEdit() {
    setEditKey((value) => value + 1);
    setIsEditing(true);
  }

  return isEditing ? (
    <CreatorForm
      key={editKey}
      profile={current}
      onCancel={() => setIsEditing(false)}
      onProfileUpdated={setCurrent}
      onSaved={(updated) => {
        setCurrent(updated);
        setIsEditing(false);
      }}
    />
  ) : (
    <CreatorOverview profile={current} onEdit={openEdit} />
  );
}

function DashboardProfileContent({ user }: { user: User }) {
  const [profile, setProfile] = useState<Profile | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [loadError, setLoadError] = useState("");
  const [reloadToken, setReloadToken] = useState(0);

  const retry = useCallback(() => {
    setReloadToken((value) => value + 1);
  }, []);

  useEffect(() => {
    let cancelled = false;

    async function load() {
      setIsLoading(true);
      setLoadError("");

      try {
        const result = await profileApi.get();

        if (cancelled) {
          return;
        }

        setProfile(result);
      } catch (error) {
        if (cancelled) {
          return;
        }

        setLoadError("Unable to load your profile.");
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    }

    void load();

    return () => {
      cancelled = true;
    };
  }, [user.id, reloadToken]);

  const isCreator = user.account_type === "creator";

  return (
    <div className="mx-auto w-full max-w-dashboard space-y-4">
      <PageHeader
        description={
          isCreator
            ? "Manage your creator profile and public information."
            : "Company details brands use across Postvertise."
        }
        actions={
          isCreator ? undefined : (
            <Button href="/dashboard/discover" size="sm" variant="secondary">
              Discover creators
            </Button>
          )
        }
      />
      <div>
        {isLoading ? <ProfileSkeleton variant={isCreator ? "creator" : "brand"} /> : null}
        {!isLoading && loadError ? (
          <ErrorState title="Unable to load your profile" message={loadError} onRetry={retry} />
        ) : null}
        {!isLoading && !loadError && isCreator ? (
          <CreatorProfileExperience
            profile={profile?.account_type === "creator" ? profile : emptyCreatorProfile()}
          />
        ) : null}
        {!isLoading && !loadError && user.account_type === "brand" ? (
          <BrandForm profile={profile?.account_type === "brand" ? profile : emptyBrandProfile()} />
        ) : null}
      </div>
    </div>
  );
}

export function DashboardProfilePage() {
  return (
    <DashboardShell title={(user) => (user.account_type === "brand" ? "Brand Profile" : "Profile")}>
      {(user) => <DashboardProfileContent user={user} />}
    </DashboardShell>
  );
}
